mirror of
https://github.com/chiteroman/PlayIntegrityFix.git
synced 2025-01-19 03:22:39 +02:00
rollback
This commit is contained in:
parent
abbe5ffb88
commit
4992274bdd
@ -2,6 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/app/src/main/cpp/libcxx" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/app/src/main/cpp/Dobby" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -12,14 +12,25 @@ android {
|
||||
applicationId = "es.chiteroman.playintegrityfix"
|
||||
minSdk = 26
|
||||
targetSdk = 34
|
||||
versionCode = 15310
|
||||
versionName = "v15.3.1"
|
||||
versionCode = 15320
|
||||
versionName = "v15.3.2"
|
||||
|
||||
packaging {
|
||||
jniLibs {
|
||||
excludes += "**/libdobby.so"
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
ndk {
|
||||
abiFilters += "arm64-v8a"
|
||||
abiFilters += "armeabi-v7a"
|
||||
jobs = Runtime.getRuntime().availableProcessors()
|
||||
cmake {
|
||||
arguments += "-DANDROID_STL=c++_static"
|
||||
arguments += "-DCMAKE_BUILD_TYPE=MinSizeRel"
|
||||
|
||||
cppFlags += "-std=c++20"
|
||||
cppFlags += "-fno-exceptions"
|
||||
cppFlags += "-fno-rtti"
|
||||
cppFlags += "-fvisibility=hidden"
|
||||
cppFlags += "-fvisibility-inlines-hidden"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -40,8 +51,9 @@ android {
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
path = file("src/main/cpp/Android.mk")
|
||||
cmake {
|
||||
path = file("src/main/cpp/CMakeLists.txt")
|
||||
version = "3.22.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := zygisk
|
||||
LOCAL_SRC_FILES := $(LOCAL_PATH)/main.cpp
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)
|
||||
|
||||
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/*.c)
|
||||
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/common/*.c)
|
||||
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/third_party/xdl/*.c)
|
||||
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/common
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/include
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/bsd
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/lss
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/third_party/xdl
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
|
||||
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/arch/arm/*.c)
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/arch/arm
|
||||
else ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
|
||||
LOCAL_SRC_FILES += $(wildcard $(LOCAL_PATH)/shadowhook/arch/arm64/*.c)
|
||||
LOCAL_C_INCLUDES += $(LOCAL_PATH)/shadowhook/arch/arm64
|
||||
endif
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libcxx
|
||||
LOCAL_LDLIBS := -llog
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(LOCAL_PATH)/libcxx/Android.mk
|
@ -1,5 +0,0 @@
|
||||
APP_STL := none
|
||||
APP_ABI := arm64-v8a armeabi-v7a
|
||||
APP_CFLAGS := -Oz -flto -fvisibility=hidden -fvisibility-inlines-hidden
|
||||
APP_CPPFLAGS := -std=c++20 -fno-exceptions -fno-rtti
|
||||
APP_LDFLAGS := -Oz -flto
|
26
app/src/main/cpp/CMakeLists.txt
Normal file
26
app/src/main/cpp/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
||||
cmake_minimum_required(VERSION 3.22.1)
|
||||
|
||||
project("playintegrityfix")
|
||||
|
||||
add_library(${CMAKE_PROJECT_NAME} SHARED main.cpp)
|
||||
|
||||
if (NOT TARGET dobby)
|
||||
set(DOBBY_DIR ${PROJECT_SOURCE_DIR}/Dobby)
|
||||
macro(SET_OPTION option value)
|
||||
set(${option} ${value} CACHE INTERNAL "" FORCE)
|
||||
endmacro()
|
||||
SET_OPTION(DOBBY_DEBUG OFF)
|
||||
SET_OPTION(DOBBY_GENERATE_SHARED OFF)
|
||||
SET_OPTION(Plugin.Android.BionicLinkerUtil ON)
|
||||
add_subdirectory(${DOBBY_DIR} dobby)
|
||||
get_property(DOBBY_INCLUDE_DIRECTORIES
|
||||
TARGET dobby
|
||||
PROPERTY INCLUDE_DIRECTORIES)
|
||||
include_directories(
|
||||
.
|
||||
${DOBBY_INCLUDE_DIRECTORIES}
|
||||
$<TARGET_PROPERTY:dobby,INCLUDE_DIRECTORIES>
|
||||
)
|
||||
endif ()
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE log dobby)
|
1
app/src/main/cpp/Dobby
Submodule
1
app/src/main/cpp/Dobby
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 6813ca76ddeafcaece525bf8c6cde7ff4c21d3ce
|
@ -1,88 +0,0 @@
|
||||
BasedOnStyle: LLVM
|
||||
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: Consecutive
|
||||
AlignConsecutiveBitFields: Consecutive
|
||||
AlignEscapedNewlines: Right
|
||||
AlignOperands: AlignAfterOperator
|
||||
AlignTrailingComments: true
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: true
|
||||
AllowShortFunctionsOnASingleLine: true
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AttributeMacros: ['_LIBCPP_HIDE_FROM_ABI',
|
||||
'_LIBCPP_CONSTEXPR',
|
||||
'_LIBCPP_CONSTEXPR_SINCE_CXX14',
|
||||
'_LIBCPP_CONSTEXPR_SINCE_CXX17',
|
||||
'_LIBCPP_CONSTEXPR_SINCE_CXX20',
|
||||
'_LIBCPP_CONSTEXPR_SINCE_CXX23',
|
||||
'_LIBCPP_ALIGNOF',
|
||||
'_ALIGNAS_TYPE',
|
||||
'_ALIGNAS',
|
||||
'_LIBCPP_NORETURN',
|
||||
'_LIBCPP_ALWAYS_INLINE',
|
||||
'_LIBCPP_DISABLE_EXTENTSION_WARNING',
|
||||
'_LIBCPP_HIDDEN',
|
||||
'_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS',
|
||||
'_LIBCPP_FUNC_VIS',
|
||||
'_LIBCPP_TYPE_VIS',
|
||||
'_LIBCPP_TEMPLATE_VIS',
|
||||
'_LIBCPP_TEMPLATE_DATA_VIS',
|
||||
'_LIBCPP_EXPORTED_FROM_ABI',
|
||||
'_LIBCPP_OVERRIDABLE_FUNC_VIS',
|
||||
'_LIBCPP_EXCEPTION_ABI',
|
||||
'_LIBCPP_ENUM_VIS',
|
||||
'_LIBCPP_EXTERN_TEMPLATE_TYPE_VIS',
|
||||
'_LIBCPP_INTERNAL_LINKAGE',
|
||||
'_LIBCPP_EXCLUDE_FROM_EXPLICIT_INSTANTIATION',
|
||||
'_LIBCPP_HIDE_FROM_ABI_AFTER_V1',
|
||||
'_LIBCPP_INLINE_VISIBILITY',
|
||||
'_LIBCPP_CONSTEVAL',
|
||||
'_LIBCPP_NOALIAS',
|
||||
'_LIBCPP_USING_IF_EXISTS',
|
||||
'_LIBCPP_DEPRECATED',
|
||||
'_LIBCPP_DEPRECATED_IN_CXX11',
|
||||
'_LIBCPP_DEPRECATED_IN_CXX14',
|
||||
'_LIBCPP_DEPRECATED_IN_CXX17',
|
||||
'_LIBCPP_DEPRECATED_IN_CXX20',
|
||||
'_LIBCPP_NODISCARD',
|
||||
'_LIBCPP_NODISCARD_EXT',
|
||||
'_LIBCPP_NO_DESTROY',
|
||||
'_LIBCPP_WEAK',
|
||||
'_LIBCPP_CONSTINIT',
|
||||
'_LIBCPP_FALLTHROUGH',
|
||||
'_LIBCPP_STANDALONE_DEBUG',
|
||||
'_LIBCPP_NO_UNIQUE_ADDRESS',
|
||||
]
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakInheritanceList: BeforeColon
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: Always
|
||||
IndentWrappedFunctionNames: false
|
||||
IndentRequires: true
|
||||
InsertTrailingCommas: Wrapped
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
PackConstructorInitializers: NextLine
|
||||
|
||||
PenaltyIndentedWhitespace: 2
|
||||
|
||||
Language: Cpp
|
||||
Standard: c++20
|
||||
SpacesInAngles: Leave
|
||||
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
PointerAlignment: Left
|
||||
|
||||
|
||||
# Disable formatting options which may break tests.
|
||||
SortIncludes: false
|
||||
ReflowComments: false
|
||||
|
||||
# libc++'s preferred indentions of preprocessor statements.
|
||||
IndentPPDirectives: AfterHash
|
||||
|
||||
# libc++ has some long names so we need more than the 80 column limit imposed by LLVM style, for sensible formatting
|
||||
ColumnLimit: 120
|
@ -1,67 +0,0 @@
|
||||
Checks: >
|
||||
bugprone-copy-constructor-init,
|
||||
bugprone-dangling-handle,
|
||||
bugprone-infinite-loop,
|
||||
bugprone-stringview-nullptr,
|
||||
bugprone-use-after-move,
|
||||
|
||||
llvm-include-order,
|
||||
llvm-namespace-comment,
|
||||
|
||||
misc-definitions-in-headers,
|
||||
misc-misplaced-const,
|
||||
misc-non-copyable-objects,
|
||||
misc-uniqueptr-reset-release,
|
||||
|
||||
modernize-loop-convert,
|
||||
modernize-redundant-void-arg,
|
||||
modernize-use-override,
|
||||
|
||||
readability-duplicate-include,
|
||||
readability-identifier-naming,
|
||||
readability-function-cognitive-complexity,
|
||||
readability-function-size,
|
||||
readability-misplaced-array-index,
|
||||
readability-redundant-control-flow,
|
||||
readability-redundant-function-ptr-dereference,
|
||||
readability-redundant-preprocessor,
|
||||
readability-simplify-boolean-expr,
|
||||
readability-simplify-subscript-expr,
|
||||
readability-uniqueptr-delete-release,
|
||||
|
||||
CheckOptions:
|
||||
- key: readability-function-cognitive-complexity.Threshold
|
||||
value: 143 # TODO: bring that number down
|
||||
- key: readability-function-size.LineThreshold
|
||||
value: 194 # TODO: bring that number down
|
||||
- key: readability-identifier-naming.GetConfigPerFile
|
||||
value: false
|
||||
- key: readability-identifier-naming.ParameterCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.ParameterPrefix
|
||||
value: __
|
||||
- key: readability-identifier-naming.PrivateMemberCase
|
||||
value: lower_case
|
||||
- key: readability-identifier-naming.PrivateMemberPrefix
|
||||
value: __
|
||||
- key: readability-identifier-naming.PrivateMemberSuffix
|
||||
value: _
|
||||
|
||||
# TODO: investigate these checks
|
||||
# bugprone-branch-clone,
|
||||
# bugprone-macro-parentheses,
|
||||
# cppcoreguidelines-prefer-member-initializer,
|
||||
# misc-unused-parameters,
|
||||
# modernize-use-bool-literals,
|
||||
# modernize-use-default-member-init,
|
||||
# modernize-use-equals-default,
|
||||
# modernize-use-equals-delete,
|
||||
# modernize-use-nullptr,
|
||||
# portability-restrict-system-includes,
|
||||
# readability-function-cognitive-complexity,
|
||||
# readability-implicit-bool-conversion,
|
||||
# readability-isolate-declaration,
|
||||
# readability-redundant-access-specifiers,
|
||||
# readability-redundant-declaration,
|
||||
# readability-redundant-member-init,
|
||||
#
|
55
app/src/main/cpp/libcxx/.gitignore
vendored
55
app/src/main/cpp/libcxx/.gitignore
vendored
@ -1,55 +0,0 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
#lib/ # We actually have things checked in to lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# MSVC libraries test harness
|
||||
env.lst
|
||||
keep.lst
|
||||
|
||||
# Editor by-products
|
||||
.vscode/
|
@ -1,114 +0,0 @@
|
||||
# This file is dual licensed under the MIT and the University of Illinois Open
|
||||
# Source Licenses. See LICENSE.TXT for details.
|
||||
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
# libcxx defines
|
||||
libcxx_includes := $(LOCAL_PATH)/include $(LOCAL_PATH)/src
|
||||
libcxx_export_includes := $(libcxx_includes)
|
||||
libcxx_sources := \
|
||||
algorithm.cpp \
|
||||
any.cpp \
|
||||
atomic.cpp \
|
||||
barrier.cpp \
|
||||
bind.cpp \
|
||||
charconv.cpp \
|
||||
chrono.cpp \
|
||||
condition_variable.cpp \
|
||||
condition_variable_destructor.cpp \
|
||||
debug.cpp \
|
||||
exception.cpp \
|
||||
filesystem/directory_iterator.cpp \
|
||||
filesystem/int128_builtins.cpp \
|
||||
filesystem/operations.cpp \
|
||||
functional.cpp \
|
||||
future.cpp \
|
||||
hash.cpp \
|
||||
ios.cpp \
|
||||
ios.instantiations.cpp \
|
||||
iostream.cpp \
|
||||
legacy_debug_handler.cpp \
|
||||
legacy_pointer_safety.cpp \
|
||||
locale.cpp \
|
||||
memory.cpp \
|
||||
memory_resource.cpp \
|
||||
mutex.cpp \
|
||||
mutex_destructor.cpp \
|
||||
new.cpp \
|
||||
optional.cpp \
|
||||
random_shuffle.cpp \
|
||||
random.cpp \
|
||||
regex.cpp \
|
||||
shared_mutex.cpp \
|
||||
stdexcept.cpp \
|
||||
string.cpp \
|
||||
strstream.cpp \
|
||||
system_error.cpp \
|
||||
thread.cpp \
|
||||
typeinfo.cpp \
|
||||
utility.cpp \
|
||||
valarray.cpp \
|
||||
variant.cpp \
|
||||
vector.cpp \
|
||||
verbose_abort.cpp \
|
||||
|
||||
libcxx_sources := $(libcxx_sources:%=src/%)
|
||||
|
||||
libcxx_export_cxxflags :=
|
||||
|
||||
libcxx_cxxflags := \
|
||||
-std=c++20 \
|
||||
-fvisibility-global-new-delete-hidden \
|
||||
-fvisibility=hidden -fvisibility-inlines-hidden \
|
||||
-DLIBCXX_BUILDING_LIBCXXABI \
|
||||
-D_LIBCPP_NO_EXCEPTIONS \
|
||||
-D_LIBCPP_NO_RTTI \
|
||||
-D_LIBCPP_BUILDING_LIBRARY \
|
||||
-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS \
|
||||
-D__STDC_FORMAT_MACROS \
|
||||
$(libcxx_export_cxxflags) \
|
||||
|
||||
|
||||
libcxx_ldflags :=
|
||||
libcxx_export_ldflags :=
|
||||
|
||||
# libcxxabi defines
|
||||
libcxxabi_src_files := \
|
||||
abort_message.cpp \
|
||||
cxa_aux_runtime.cpp \
|
||||
cxa_default_handlers.cpp \
|
||||
cxa_exception_storage.cpp \
|
||||
cxa_guard.cpp \
|
||||
cxa_handlers.cpp \
|
||||
cxa_noexception.cpp \
|
||||
cxa_thread_atexit.cpp \
|
||||
cxa_vector.cpp \
|
||||
cxa_virtual.cpp \
|
||||
stdlib_exception.cpp \
|
||||
stdlib_new_delete.cpp \
|
||||
stdlib_stdexcept.cpp \
|
||||
stdlib_typeinfo.cpp \
|
||||
|
||||
libcxxabi_src_files := $(libcxxabi_src_files:%=src/abi/%)
|
||||
|
||||
libcxxabi_includes := \
|
||||
$(LOCAL_PATH)/include \
|
||||
$(LOCAL_PATH)/include/abi \
|
||||
|
||||
libcxxabi_cflags := -D__STDC_FORMAT_MACROS
|
||||
libcxxabi_cppflags := \
|
||||
-D_LIBCXXABI_NO_EXCEPTIONS \
|
||||
-Wno-macro-redefined \
|
||||
-Wno-unknown-attributes \
|
||||
-DHAS_THREAD_LOCAL
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libcxx
|
||||
LOCAL_SRC_FILES := $(libcxx_sources) $(libcxxabi_src_files)
|
||||
LOCAL_C_INCLUDES := $(libcxx_includes) $(libcxxabi_includes)
|
||||
LOCAL_CPPFLAGS := $(libcxx_cxxflags) $(libcxxabi_cppflags) -ffunction-sections -fdata-sections
|
||||
LOCAL_EXPORT_C_INCLUDES := $(libcxx_export_includes)
|
||||
LOCAL_EXPORT_CPPFLAGS := $(libcxx_export_cxxflags)
|
||||
LOCAL_EXPORT_LDFLAGS := $(libcxx_export_ldflags)
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
@ -1,937 +0,0 @@
|
||||
# See https://libcxx.llvm.org/docs/BuildingLibcxx.html for instructions on how
|
||||
# to build libcxx with CMake.
|
||||
|
||||
#===============================================================================
|
||||
# Setup Project
|
||||
#===============================================================================
|
||||
cmake_minimum_required(VERSION 3.13.4)
|
||||
|
||||
set(LLVM_COMMON_CMAKE_UTILS "${CMAKE_CURRENT_SOURCE_DIR}/../cmake")
|
||||
|
||||
# Add path for custom modules
|
||||
list(INSERT CMAKE_MODULE_PATH 0
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules"
|
||||
"${LLVM_COMMON_CMAKE_UTILS}"
|
||||
"${LLVM_COMMON_CMAKE_UTILS}/Modules"
|
||||
)
|
||||
|
||||
set(CMAKE_FOLDER "libc++")
|
||||
|
||||
set(LIBCXX_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(LIBCXX_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(LIBCXX_BINARY_INCLUDE_DIR "${LIBCXX_BINARY_DIR}/include/c++build")
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# Require out of source build.
|
||||
include(MacroEnsureOutOfSourceBuild)
|
||||
MACRO_ENSURE_OUT_OF_SOURCE_BUILD(
|
||||
"${PROJECT_NAME} requires an out of source build. Please create a separate
|
||||
build directory and run 'cmake /path/to/${PROJECT_NAME} [options]' there."
|
||||
)
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC")
|
||||
message(STATUS "Configuring for clang-cl")
|
||||
set(LIBCXX_TARGETING_CLANG_CL ON)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
set(LIBCXX_TARGETING_MSVC ON)
|
||||
message(STATUS "Configuring for MSVC")
|
||||
else()
|
||||
set(LIBCXX_TARGETING_MSVC OFF)
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
# Setup CMake Options
|
||||
#===============================================================================
|
||||
include(CMakeDependentOption)
|
||||
include(HandleCompilerRT)
|
||||
|
||||
# Basic options ---------------------------------------------------------------
|
||||
option(LIBCXX_ENABLE_ASSERTIONS
|
||||
"Enable assertions inside the compiled library, and at the same time make it the
|
||||
default when compiling user code. Note that assertions can be enabled or disabled
|
||||
by users in their own code regardless of this option." OFF)
|
||||
option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON)
|
||||
option(LIBCXX_ENABLE_STATIC "Build libc++ as a static library." ON)
|
||||
set(ENABLE_FILESYSTEM_DEFAULT ON)
|
||||
if (WIN32 AND NOT MINGW)
|
||||
# Filesystem is buildable for windows, but it requires __int128 helper
|
||||
# functions, that currently are provided by libgcc or compiler_rt builtins.
|
||||
# These are available in MinGW environments, but not currently in MSVC
|
||||
# environments.
|
||||
set(ENABLE_FILESYSTEM_DEFAULT OFF)
|
||||
endif()
|
||||
option(LIBCXX_ENABLE_FILESYSTEM "Build filesystem as part of the main libc++ library"
|
||||
${ENABLE_FILESYSTEM_DEFAULT})
|
||||
option(LIBCXX_INCLUDE_TESTS "Build the libc++ tests." ${LLVM_INCLUDE_TESTS})
|
||||
option(LIBCXX_ENABLE_PARALLEL_ALGORITHMS "Enable the parallel algorithms library. This requires the PSTL to be available." OFF)
|
||||
option(LIBCXX_ENABLE_DEBUG_MODE
|
||||
"Whether to build libc++ with the debug mode enabled.
|
||||
By default, this is turned off. Turning it on results in a different ABI (additional
|
||||
symbols but also potentially different layouts of types), and one should not mix code
|
||||
built against a dylib that has debug mode and code built against a regular dylib." OFF)
|
||||
option(LIBCXX_ENABLE_RANDOM_DEVICE
|
||||
"Whether to include support for std::random_device in the library. Disabling
|
||||
this can be useful when building the library for platforms that don't have
|
||||
a source of randomness, such as some embedded platforms. When this is not
|
||||
supported, most of <random> will still be available, but std::random_device
|
||||
will not." ON)
|
||||
option(LIBCXX_ENABLE_LOCALIZATION
|
||||
"Whether to include support for localization in the library. Disabling
|
||||
localization can be useful when porting to platforms that don't support
|
||||
the C locale API (e.g. embedded). When localization is not supported,
|
||||
several parts of the library will be disabled: <iostream>, <regex>, <locale>
|
||||
will be completely unusable, and other parts may be only partly available." ON)
|
||||
option(LIBCXX_ENABLE_UNICODE
|
||||
"Whether to include support for Unicode in the library. Disabling Unicode can
|
||||
be useful when porting to platforms that don't support UTF-8 encoding (e.g.
|
||||
embedded)." ON)
|
||||
option(LIBCXX_ENABLE_WIDE_CHARACTERS
|
||||
"Whether to include support for wide characters in the library. Disabling
|
||||
wide character support can be useful when porting to platforms that don't
|
||||
support the C functionality for wide characters. When wide characters are
|
||||
not supported, several parts of the library will be disabled, notably the
|
||||
wide character specializations of std::basic_string." ON)
|
||||
option(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS
|
||||
"Whether to turn on vendor availability annotations on declarations that depend
|
||||
on definitions in a shared library. By default, we assume that we're not building
|
||||
libc++ for any specific vendor, and we disable those annotations. Vendors wishing
|
||||
to provide compile-time errors when using features unavailable on some version of
|
||||
the shared library they shipped should turn this on and see `include/__availability`
|
||||
for more details." OFF)
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
set(LIBCXX_DEFAULT_TEST_CONFIG "llvm-libc++-shared-gcc.cfg.in")
|
||||
elseif(MINGW)
|
||||
set(LIBCXX_DEFAULT_TEST_CONFIG "llvm-libc++-mingw.cfg.in")
|
||||
elseif(WIN32) # clang-cl
|
||||
if (LIBCXX_ENABLE_SHARED)
|
||||
set(LIBCXX_DEFAULT_TEST_CONFIG "llvm-libc++-shared-clangcl.cfg.in")
|
||||
else()
|
||||
set(LIBCXX_DEFAULT_TEST_CONFIG "llvm-libc++-static-clangcl.cfg.in")
|
||||
endif()
|
||||
else()
|
||||
if (LIBCXX_ENABLE_SHARED)
|
||||
set(LIBCXX_DEFAULT_TEST_CONFIG "llvm-libc++-shared.cfg.in")
|
||||
else()
|
||||
set(LIBCXX_DEFAULT_TEST_CONFIG "llvm-libc++-static.cfg.in")
|
||||
endif()
|
||||
endif()
|
||||
set(LIBCXX_TEST_CONFIG "${LIBCXX_DEFAULT_TEST_CONFIG}" CACHE STRING
|
||||
"The path to the Lit testing configuration to use when running the tests.
|
||||
If a relative path is provided, it is assumed to be relative to '<monorepo>/libcxx/test/configs'.")
|
||||
if (NOT IS_ABSOLUTE "${LIBCXX_TEST_CONFIG}")
|
||||
set(LIBCXX_TEST_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/test/configs/${LIBCXX_TEST_CONFIG}")
|
||||
endif()
|
||||
message(STATUS "Using libc++ testing configuration: ${LIBCXX_TEST_CONFIG}")
|
||||
set(LIBCXX_TEST_PARAMS "" CACHE STRING
|
||||
"A list of parameters to run the Lit test suite with.")
|
||||
|
||||
# Benchmark options -----------------------------------------------------------
|
||||
option(LIBCXX_INCLUDE_BENCHMARKS "Build the libc++ benchmarks and their dependencies" ON)
|
||||
|
||||
set(LIBCXX_BENCHMARK_TEST_ARGS_DEFAULT --benchmark_min_time=0.01)
|
||||
set(LIBCXX_BENCHMARK_TEST_ARGS "${LIBCXX_BENCHMARK_TEST_ARGS_DEFAULT}" CACHE STRING
|
||||
"Arguments to pass when running the benchmarks using check-cxx-benchmarks")
|
||||
|
||||
set(LIBCXX_BENCHMARK_NATIVE_STDLIB "" CACHE STRING
|
||||
"Build the benchmarks against the specified native STL.
|
||||
The value must be one of libc++/libstdc++")
|
||||
set(LIBCXX_BENCHMARK_NATIVE_GCC_TOOLCHAIN "" CACHE STRING
|
||||
"Use alternate GCC toolchain when building the native benchmarks")
|
||||
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB)
|
||||
if (NOT (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libc++"
|
||||
OR LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libstdc++"))
|
||||
message(FATAL_ERROR "Invalid value for LIBCXX_BENCHMARK_NATIVE_STDLIB: "
|
||||
"'${LIBCXX_BENCHMARK_NATIVE_STDLIB}'")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
option(LIBCXX_INCLUDE_DOCS "Build the libc++ documentation." ${LLVM_INCLUDE_DOCS})
|
||||
set(LIBCXX_LIBDIR_SUFFIX "${LLVM_LIBDIR_SUFFIX}" CACHE STRING
|
||||
"Define suffix of library directory name (32/64)")
|
||||
option(LIBCXX_INSTALL_HEADERS "Install the libc++ headers." ON)
|
||||
option(LIBCXX_INSTALL_LIBRARY "Install the libc++ library." ON)
|
||||
cmake_dependent_option(LIBCXX_INSTALL_STATIC_LIBRARY
|
||||
"Install the static libc++ library." ON
|
||||
"LIBCXX_ENABLE_STATIC;LIBCXX_INSTALL_LIBRARY" OFF)
|
||||
cmake_dependent_option(LIBCXX_INSTALL_SHARED_LIBRARY
|
||||
"Install the shared libc++ library." ON
|
||||
"LIBCXX_ENABLE_SHARED;LIBCXX_INSTALL_LIBRARY" OFF)
|
||||
|
||||
option(LIBCXX_ABI_UNSTABLE "Use the unstable ABI of libc++. This is equivalent to specifying LIBCXX_ABI_VERSION=n, where n is the not-yet-stable version." OFF)
|
||||
if (LIBCXX_ABI_UNSTABLE)
|
||||
set(abi_version "2")
|
||||
else()
|
||||
set(abi_version "1")
|
||||
endif()
|
||||
set(LIBCXX_ABI_VERSION "${abi_version}" CACHE STRING
|
||||
"ABI version of libc++. Can be either 1 or 2, where 2 is currently the unstable ABI.
|
||||
Defaults to 1 unless LIBCXX_ABI_UNSTABLE is specified, in which case this is 2.")
|
||||
set(LIBCXX_LIBRARY_VERSION "${LIBCXX_ABI_VERSION}.0" CACHE STRING
|
||||
"Version of libc++. This will be reflected in the name of the shared library produced.
|
||||
For example, -DLIBCXX_LIBRARY_VERSION=x.y will result in the library being named
|
||||
libc++.x.y.dylib, along with the usual symlinks pointing to that. On Apple platforms,
|
||||
this also controls the linker's 'current_version' property.")
|
||||
set(LIBCXX_ABI_NAMESPACE "__${LIBCXX_ABI_VERSION}" CACHE STRING "The inline ABI namespace used by libc++. It defaults to __n where `n` is the current ABI version.")
|
||||
if (NOT LIBCXX_ABI_NAMESPACE MATCHES "__.*")
|
||||
message(FATAL_ERROR "LIBCXX_ABI_NAMESPACE must be a reserved identifier, got '${LIBCXX_ABI_NAMESPACE}'.")
|
||||
endif()
|
||||
option(LIBCXX_ABI_FORCE_ITANIUM "Ignore auto-detection and force use of the Itanium ABI.")
|
||||
option(LIBCXX_ABI_FORCE_MICROSOFT "Ignore auto-detection and force use of the Microsoft ABI.")
|
||||
|
||||
set(LIBCXX_TYPEINFO_COMPARISON_IMPLEMENTATION "default" CACHE STRING
|
||||
"Override the implementation to use for comparing typeinfos. By default, this
|
||||
is detected automatically by the library, but this option allows overriding
|
||||
which implementation is used unconditionally.
|
||||
|
||||
See the documentation in <libcxx/include/typeinfo> for details on what each
|
||||
value means.")
|
||||
set(TYPEINFO_COMPARISON_VALUES "default;1;2;3")
|
||||
if (NOT ("${LIBCXX_TYPEINFO_COMPARISON_IMPLEMENTATION}" IN_LIST TYPEINFO_COMPARISON_VALUES))
|
||||
message(FATAL_ERROR "Value '${LIBCXX_TYPEINFO_COMPARISON_IMPLEMENTATION}' is not a valid value for
|
||||
LIBCXX_TYPEINFO_COMPARISON_IMPLEMENTATION")
|
||||
endif()
|
||||
|
||||
set(LIBCXX_ABI_DEFINES "" CACHE STRING "A semicolon separated list of ABI macros to define in the site config header.")
|
||||
option(LIBCXX_EXTRA_SITE_DEFINES "Extra defines to add into __config_site")
|
||||
option(LIBCXX_USE_COMPILER_RT "Use compiler-rt instead of libgcc" OFF)
|
||||
|
||||
option(LIBCXX_ENABLE_BACKWARDS_COMPATIBILITY_DEBUG_MODE_SYMBOLS
|
||||
"Whether to include the old Debug mode symbols in the compiled library. This
|
||||
is provided for backwards compatibility since the compiled library used to
|
||||
always contain those symbols, regardless of whether the library was built
|
||||
with the debug mode enabled. This is OFF by default, please contact the libc++
|
||||
developers if you need to turn this on, as this will be removed in LLVM 16." OFF)
|
||||
|
||||
# ABI Library options ---------------------------------------------------------
|
||||
if (LIBCXX_TARGETING_MSVC)
|
||||
set(LIBCXX_DEFAULT_ABI_LIBRARY "vcruntime")
|
||||
elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
set(LIBCXX_DEFAULT_ABI_LIBRARY "libcxxrt")
|
||||
else()
|
||||
set(LIBCXX_DEFAULT_ABI_LIBRARY "libcxxabi")
|
||||
endif()
|
||||
|
||||
set(LIBCXX_SUPPORTED_ABI_LIBRARIES none libcxxabi system-libcxxabi libcxxrt libstdc++ libsupc++ vcruntime)
|
||||
set(LIBCXX_CXX_ABI "${LIBCXX_DEFAULT_ABI_LIBRARY}" CACHE STRING "Specify C++ ABI library to use. Supported values are ${LIBCXX_SUPPORTED_ABI_LIBRARIES}.")
|
||||
if (NOT "${LIBCXX_CXX_ABI}" IN_LIST LIBCXX_SUPPORTED_ABI_LIBRARIES)
|
||||
message(FATAL_ERROR "Unsupported C++ ABI library: '${LIBCXX_CXX_ABI}'. Supported values are ${LIBCXX_SUPPORTED_ABI_LIBRARIES}.")
|
||||
endif()
|
||||
|
||||
option(LIBCXX_ENABLE_STATIC_ABI_LIBRARY
|
||||
"Use a static copy of the ABI library when linking libc++.
|
||||
This option cannot be used with LIBCXX_ENABLE_ABI_LINKER_SCRIPT." OFF)
|
||||
|
||||
cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY
|
||||
"Statically link the ABI library to static library" ON
|
||||
"LIBCXX_ENABLE_STATIC_ABI_LIBRARY" OFF)
|
||||
|
||||
cmake_dependent_option(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY
|
||||
"Statically link the ABI library to shared library" ON
|
||||
"LIBCXX_ENABLE_STATIC_ABI_LIBRARY" OFF)
|
||||
|
||||
# Generate and install a linker script inplace of libc++.so. The linker script
|
||||
# will link libc++ to the correct ABI library. This option is on by default
|
||||
# on UNIX platforms other than Apple unless 'LIBCXX_ENABLE_STATIC_ABI_LIBRARY'
|
||||
# is on. This option is also disabled when the ABI library is not specified
|
||||
# or is specified to be "none".
|
||||
set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE OFF)
|
||||
if (LLVM_HAVE_LINK_VERSION_SCRIPT AND NOT LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY
|
||||
AND NOT LIBCXX_CXX_ABI STREQUAL "none"
|
||||
AND Python3_EXECUTABLE
|
||||
AND LIBCXX_ENABLE_SHARED)
|
||||
set(ENABLE_LINKER_SCRIPT_DEFAULT_VALUE ON)
|
||||
endif()
|
||||
|
||||
option(LIBCXX_ENABLE_ABI_LINKER_SCRIPT
|
||||
"Use and install a linker script for the given ABI library"
|
||||
${ENABLE_LINKER_SCRIPT_DEFAULT_VALUE})
|
||||
|
||||
option(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS
|
||||
"Build libc++ with definitions for operator new/delete. These are normally
|
||||
defined in libc++abi, but this option can be used to define them in libc++
|
||||
instead. If you define them in libc++, make sure they are NOT defined in
|
||||
libc++abi. Doing otherwise is an ODR violation." OFF)
|
||||
# Build libc++abi with libunwind. We need this option to determine whether to
|
||||
# link with libunwind or libgcc_s while running the test cases.
|
||||
option(LIBCXXABI_USE_LLVM_UNWINDER "Build and use the LLVM unwinder." OFF)
|
||||
|
||||
# Target options --------------------------------------------------------------
|
||||
option(LIBCXX_BUILD_32_BITS "Build 32 bit multilib libc++. This option is not supported anymore when building the runtimes. Please specify a full triple instead." ${LLVM_BUILD_32_BITS})
|
||||
if (LIBCXX_BUILD_32_BITS)
|
||||
message(FATAL_ERROR "LIBCXX_BUILD_32_BITS is not supported anymore when building the runtimes, please specify a full triple instead.")
|
||||
endif()
|
||||
|
||||
# TODO: Remove this after branching for LLVM 15
|
||||
if(LIBCXX_SYSROOT OR LIBCXX_TARGET_TRIPLE OR LIBCXX_GCC_TOOLCHAIN)
|
||||
message(WARNING "LIBCXX_SYSROOT, LIBCXX_TARGET_TRIPLE and LIBCXX_GCC_TOOLCHAIN are not supported anymore, please use the native CMake equivalents instead")
|
||||
endif()
|
||||
|
||||
# Feature options -------------------------------------------------------------
|
||||
option(LIBCXX_ENABLE_EXCEPTIONS "Use exceptions." ON)
|
||||
option(LIBCXX_ENABLE_RTTI "Use run time type information." ON)
|
||||
option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON)
|
||||
option(LIBCXX_ENABLE_MONOTONIC_CLOCK
|
||||
"Build libc++ with support for a monotonic clock.
|
||||
This option may only be set to OFF when LIBCXX_ENABLE_THREADS=OFF." ON)
|
||||
option(LIBCXX_HAS_MUSL_LIBC "Build libc++ with support for the Musl C library" OFF)
|
||||
option(LIBCXX_HAS_PTHREAD_API "Ignore auto-detection and force use of pthread API" OFF)
|
||||
option(LIBCXX_HAS_WIN32_THREAD_API "Ignore auto-detection and force use of win32 thread API" OFF)
|
||||
option(LIBCXX_HAS_EXTERNAL_THREAD_API
|
||||
"Build libc++ with an externalized threading API.
|
||||
This option may only be set to ON when LIBCXX_ENABLE_THREADS=ON." OFF)
|
||||
option(LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY
|
||||
"Build libc++ with an externalized threading library.
|
||||
This option may only be set to ON when LIBCXX_ENABLE_THREADS=ON" OFF)
|
||||
|
||||
# Misc options ----------------------------------------------------------------
|
||||
# FIXME: Turn -pedantic back ON. It is currently off because it warns
|
||||
# about #include_next which is used everywhere.
|
||||
option(LIBCXX_ENABLE_PEDANTIC "Compile with pedantic enabled." OFF)
|
||||
option(LIBCXX_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
|
||||
option(LIBCXX_DISABLE_MACRO_CONFLICT_WARNINGS "Disable #warnings about conflicting macros." OFF)
|
||||
|
||||
option(LIBCXX_GENERATE_COVERAGE "Enable generating code coverage." OFF)
|
||||
set(LIBCXX_COVERAGE_LIBRARY "" CACHE STRING
|
||||
"The Profile-rt library used to build with code coverage")
|
||||
|
||||
set(LIBCXX_CONFIGURE_IDE_DEFAULT OFF)
|
||||
if (XCODE OR MSVC_IDE)
|
||||
set(LIBCXX_CONFIGURE_IDE_DEFAULT ON)
|
||||
endif()
|
||||
option(LIBCXX_CONFIGURE_IDE "Configure libcxx for use within an IDE"
|
||||
${LIBCXX_CONFIGURE_IDE_DEFAULT})
|
||||
|
||||
set(LIBCXX_HERMETIC_STATIC_LIBRARY_DEFAULT OFF)
|
||||
if (WIN32)
|
||||
set(LIBCXX_HERMETIC_STATIC_LIBRARY_DEFAULT ON)
|
||||
endif()
|
||||
option(LIBCXX_HERMETIC_STATIC_LIBRARY
|
||||
"Do not export any symbols from the static library." ${LIBCXX_HERMETIC_STATIC_LIBRARY_DEFAULT})
|
||||
|
||||
#===============================================================================
|
||||
# Check option configurations
|
||||
#===============================================================================
|
||||
|
||||
# Ensure LIBCXX_ENABLE_MONOTONIC_CLOCK is set to ON only when
|
||||
# LIBCXX_ENABLE_THREADS is on.
|
||||
if(LIBCXX_ENABLE_THREADS AND NOT LIBCXX_ENABLE_MONOTONIC_CLOCK)
|
||||
message(FATAL_ERROR "LIBCXX_ENABLE_MONOTONIC_CLOCK can only be set to OFF"
|
||||
" when LIBCXX_ENABLE_THREADS is also set to OFF.")
|
||||
endif()
|
||||
|
||||
if(NOT LIBCXX_ENABLE_THREADS)
|
||||
if(LIBCXX_HAS_PTHREAD_API)
|
||||
message(FATAL_ERROR "LIBCXX_HAS_PTHREAD_API can only be set to ON"
|
||||
" when LIBCXX_ENABLE_THREADS is also set to ON.")
|
||||
endif()
|
||||
if(LIBCXX_HAS_EXTERNAL_THREAD_API)
|
||||
message(FATAL_ERROR "LIBCXX_HAS_EXTERNAL_THREAD_API can only be set to ON"
|
||||
" when LIBCXX_ENABLE_THREADS is also set to ON.")
|
||||
endif()
|
||||
if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
message(FATAL_ERROR "LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY can only be set "
|
||||
"to ON when LIBCXX_ENABLE_THREADS is also set to ON.")
|
||||
endif()
|
||||
if (LIBCXX_HAS_WIN32_THREAD_API)
|
||||
message(FATAL_ERROR "LIBCXX_HAS_WIN32_THREAD_API can only be set to ON"
|
||||
" when LIBCXX_ENABLE_THREADS is also set to ON.")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
if (LIBCXX_HAS_EXTERNAL_THREAD_API)
|
||||
if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
message(FATAL_ERROR "The options LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY and "
|
||||
"LIBCXX_HAS_EXTERNAL_THREAD_API cannot both be ON at "
|
||||
"the same time")
|
||||
endif()
|
||||
if (LIBCXX_HAS_PTHREAD_API)
|
||||
message(FATAL_ERROR "The options LIBCXX_HAS_EXTERNAL_THREAD_API"
|
||||
"and LIBCXX_HAS_PTHREAD_API cannot be both"
|
||||
"set to ON at the same time.")
|
||||
endif()
|
||||
if (LIBCXX_HAS_WIN32_THREAD_API)
|
||||
message(FATAL_ERROR "The options LIBCXX_HAS_EXTERNAL_THREAD_API"
|
||||
"and LIBCXX_HAS_WIN32_THREAD_API cannot be both"
|
||||
"set to ON at the same time.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LIBCXX_HAS_PTHREAD_API)
|
||||
if (LIBCXX_HAS_WIN32_THREAD_API)
|
||||
message(FATAL_ERROR "The options LIBCXX_HAS_PTHREAD_API"
|
||||
"and LIBCXX_HAS_WIN32_THREAD_API cannot be both"
|
||||
"set to ON at the same time.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Ensure LLVM_USE_SANITIZER is not specified when LIBCXX_GENERATE_COVERAGE
|
||||
# is ON.
|
||||
if (LLVM_USE_SANITIZER AND LIBCXX_GENERATE_COVERAGE)
|
||||
message(FATAL_ERROR "LLVM_USE_SANITIZER cannot be used with LIBCXX_GENERATE_COVERAGE")
|
||||
endif()
|
||||
|
||||
# Warn users that LIBCXX_ENABLE_STATIC_ABI_LIBRARY is an experimental option.
|
||||
if (LIBCXX_ENABLE_STATIC_ABI_LIBRARY)
|
||||
message(WARNING "LIBCXX_ENABLE_STATIC_ABI_LIBRARY is an experimental option")
|
||||
if (LIBCXX_ENABLE_STATIC AND NOT Python3_EXECUTABLE)
|
||||
message(FATAL_ERROR "LIBCXX_ENABLE_STATIC_ABI_LIBRARY requires python but it was not found.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
|
||||
if (APPLE)
|
||||
message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT cannot be used on APPLE targets")
|
||||
endif()
|
||||
if (NOT LIBCXX_ENABLE_SHARED)
|
||||
message(FATAL_ERROR "LIBCXX_ENABLE_ABI_LINKER_SCRIPT is only available for shared library builds.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY AND LIBCXX_ENABLE_ABI_LINKER_SCRIPT)
|
||||
message(FATAL_ERROR "Conflicting options given.
|
||||
LIBCXX_ENABLE_STATIC_ABI_LIBRARY cannot be specified with
|
||||
LIBCXX_ENABLE_ABI_LINKER_SCRIPT")
|
||||
endif()
|
||||
|
||||
if (LIBCXX_ABI_FORCE_ITANIUM AND LIBCXX_ABI_FORCE_MICROSOFT)
|
||||
message(FATAL_ERROR "Only one of LIBCXX_ABI_FORCE_ITANIUM and LIBCXX_ABI_FORCE_MICROSOFT can be specified.")
|
||||
endif ()
|
||||
|
||||
#===============================================================================
|
||||
# Configure System
|
||||
#===============================================================================
|
||||
|
||||
# TODO: Projects that depend on libc++ should use LIBCXX_GENERATED_INCLUDE_DIR
|
||||
# instead of hard-coding include/c++/v1.
|
||||
|
||||
set(LIBCXX_INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}/c++/v1" CACHE PATH
|
||||
"Path where target-agnostic libc++ headers should be installed.")
|
||||
set(LIBCXX_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH
|
||||
"Path where built libc++ runtime libraries should be installed.")
|
||||
|
||||
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
|
||||
set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
|
||||
set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1")
|
||||
set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1")
|
||||
set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
|
||||
"Path where built libc++ libraries should be installed.")
|
||||
set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1" CACHE PATH
|
||||
"Path where target-specific libc++ headers should be installed.")
|
||||
if(LIBCXX_LIBDIR_SUBDIR)
|
||||
string(APPEND LIBCXX_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR})
|
||||
string(APPEND LIBCXX_INSTALL_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR})
|
||||
endif()
|
||||
else()
|
||||
if(LLVM_LIBRARY_OUTPUT_INTDIR)
|
||||
set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
|
||||
set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1")
|
||||
else()
|
||||
set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX})
|
||||
set(LIBCXX_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include/c++/v1")
|
||||
endif()
|
||||
set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LIBCXX_GENERATED_INCLUDE_DIR}")
|
||||
set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
|
||||
"Path where built libc++ libraries should be installed.")
|
||||
set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${LIBCXX_INSTALL_INCLUDE_DIR}" CACHE PATH
|
||||
"Path where target-specific libc++ headers should be installed.")
|
||||
endif()
|
||||
|
||||
file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}")
|
||||
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${LIBCXX_LIBRARY_DIR})
|
||||
|
||||
# Declare libc++ configuration variables.
|
||||
# They are intended for use as follows:
|
||||
# LIBCXX_CXX_FLAGS: General flags for both the compiler and linker.
|
||||
# LIBCXX_COMPILE_FLAGS: Compile only flags.
|
||||
# LIBCXX_LINK_FLAGS: Linker only flags.
|
||||
# LIBCXX_LIBRARIES: libraries libc++ is linked to.
|
||||
set(LIBCXX_COMPILE_FLAGS "")
|
||||
set(LIBCXX_LINK_FLAGS "")
|
||||
set(LIBCXX_LIBRARIES "")
|
||||
|
||||
# Include macros for adding and removing libc++ flags.
|
||||
include(HandleLibcxxFlags)
|
||||
|
||||
# Target flags ================================================================
|
||||
# These flags get added to CMAKE_CXX_FLAGS and CMAKE_C_FLAGS so that
|
||||
# 'config-ix' use them during feature checks. It also adds them to both
|
||||
# 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS'
|
||||
if(ZOS)
|
||||
add_target_flags_if_supported("-fzos-le-char-mode=ebcdic")
|
||||
endif()
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "AIX")
|
||||
add_target_flags_if_supported("-mdefault-visibility-export-mapping=explicit")
|
||||
set(CMAKE_AIX_EXPORT_ALL_SYMBOLS OFF)
|
||||
endif()
|
||||
|
||||
# Configure compiler.
|
||||
include(config-ix)
|
||||
|
||||
# Configure coverage options.
|
||||
if (LIBCXX_GENERATE_COVERAGE)
|
||||
include(CodeCoverage)
|
||||
set(CMAKE_BUILD_TYPE "COVERAGE" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
|
||||
if (uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
set(LIBCXX_DEBUG_BUILD ON)
|
||||
else()
|
||||
set(LIBCXX_DEBUG_BUILD OFF)
|
||||
endif()
|
||||
|
||||
#===============================================================================
|
||||
# Setup Compiler Flags
|
||||
#===============================================================================
|
||||
|
||||
include(HandleLibCXXABI) # Setup the ABI library flags
|
||||
|
||||
# Remove flags that may have snuck in.
|
||||
# TODO: This shouldn't be necessary anymore since we don't support the Project
|
||||
# build anymore, so the rest of LLVM can't pollute our flags.
|
||||
remove_flags(-DNDEBUG -UNDEBUG -D_DEBUG -lc++abi)
|
||||
remove_flags(--stdlib=libc++ -stdlib=libc++ --stdlib=libstdc++ -stdlib=libstdc++)
|
||||
|
||||
# FIXME: Remove all debug flags and flags that change which Windows
|
||||
# default libraries are linked. Currently we only support linking the
|
||||
# non-debug DLLs
|
||||
remove_flags("/D_DEBUG" "/MTd" "/MDd" "/MT" "/Md")
|
||||
|
||||
# FIXME(EricWF): See the FIXME on LIBCXX_ENABLE_PEDANTIC.
|
||||
# Remove the -pedantic flag and -Wno-pedantic and -pedantic-errors
|
||||
# so they don't get transformed into -Wno and -errors respectively.
|
||||
remove_flags(-Wno-pedantic -pedantic-errors -pedantic)
|
||||
|
||||
# Required flags ==============================================================
|
||||
function(cxx_add_basic_build_flags target)
|
||||
|
||||
# Require C++20 for all targets. C++17 is needed to use aligned allocation
|
||||
# in the dylib. C++20 is needed to use char8_t.
|
||||
set_target_properties(${target} PROPERTIES
|
||||
CXX_STANDARD 20
|
||||
CXX_STANDARD_REQUIRED YES
|
||||
CXX_EXTENSIONS NO)
|
||||
|
||||
# When building the dylib, don't warn for unavailable aligned allocation
|
||||
# functions based on the deployment target -- they are always available
|
||||
# because they are provided by the dylib itself with the excepton of z/OS.
|
||||
if (ZOS)
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -fno-aligned-allocation)
|
||||
else()
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -faligned-allocation)
|
||||
endif()
|
||||
|
||||
# On all systems the system c++ standard library headers need to be excluded.
|
||||
# MSVC only has -X, which disables all default includes; including the crt.
|
||||
# Thus, we do nothing and hope we don't accidentally include any of the C++
|
||||
# headers
|
||||
target_add_compile_flags_if_supported(${target} PUBLIC -nostdinc++)
|
||||
|
||||
# Hide all inline function definitions which have not explicitly been marked
|
||||
# visible. This prevents new definitions for inline functions from appearing in
|
||||
# the dylib when get ODR used by another function.
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -fvisibility-inlines-hidden)
|
||||
|
||||
# Our visibility annotations are not quite right for non-Clang compilers,
|
||||
# so we end up not exporting all the symbols we should. In the future, we
|
||||
# can improve the situation by providing an explicit list of exported
|
||||
# symbols on all compilers.
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -fvisibility=hidden)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_CONFIGURE_IDE)
|
||||
# This simply allows IDE to process <experimental/coroutine>
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -fcoroutines-ts)
|
||||
endif()
|
||||
|
||||
# Let the library headers know they are currently being used to build the
|
||||
# library.
|
||||
target_compile_definitions(${target} PRIVATE -D_LIBCPP_BUILDING_LIBRARY)
|
||||
|
||||
if (NOT LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS)
|
||||
target_compile_definitions(${target} PRIVATE -D_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS)
|
||||
endif()
|
||||
|
||||
if (C_SUPPORTS_COMMENT_LIB_PRAGMA)
|
||||
if (LIBCXX_HAS_PTHREAD_LIB)
|
||||
target_compile_definitions(${target} PRIVATE -D_LIBCPP_LINK_PTHREAD_LIB)
|
||||
endif()
|
||||
if (LIBCXX_HAS_RT_LIB)
|
||||
target_compile_definitions(${target} PRIVATE -D_LIBCPP_LINK_RT_LIB)
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Warning flags ===============================================================
|
||||
function(cxx_add_warning_flags target)
|
||||
target_compile_definitions(${target} PUBLIC -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||
if (MSVC)
|
||||
# -W4 is the cl.exe/clang-cl equivalent of -Wall. (In cl.exe and clang-cl,
|
||||
# -Wall is equivalent to -Weverything in GCC style compiler drivers.)
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -W4)
|
||||
else()
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -Wall)
|
||||
endif()
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -Wextra -W -Wwrite-strings
|
||||
-Wno-unused-parameter -Wno-long-long
|
||||
-Werror=return-type -Wextra-semi -Wundef
|
||||
-Wformat-nonliteral)
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE
|
||||
-Wno-user-defined-literals
|
||||
-Wno-covered-switch-default
|
||||
-Wno-suggest-override
|
||||
)
|
||||
if (LIBCXX_TARGETING_CLANG_CL)
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE
|
||||
-Wno-c++98-compat
|
||||
-Wno-c++98-compat-pedantic
|
||||
-Wno-c++11-compat
|
||||
-Wno-undef
|
||||
-Wno-reserved-id-macro
|
||||
-Wno-gnu-include-next
|
||||
-Wno-gcc-compat # For ignoring "'diagnose_if' is a clang extension" warnings
|
||||
-Wno-zero-as-null-pointer-constant # FIXME: Remove this and fix all occurrences.
|
||||
-Wno-deprecated-dynamic-exception-spec # For auto_ptr
|
||||
-Wno-sign-conversion
|
||||
-Wno-old-style-cast
|
||||
-Wno-deprecated # FIXME: Remove this and fix all occurrences.
|
||||
-Wno-shift-sign-overflow # FIXME: Why do we need this with clang-cl but not clang?
|
||||
-Wno-double-promotion # FIXME: remove me
|
||||
)
|
||||
endif()
|
||||
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE
|
||||
-Wno-attributes
|
||||
-Wno-literal-suffix
|
||||
-Wno-c++14-compat
|
||||
-Wno-noexcept-type
|
||||
-Wno-suggest-override)
|
||||
endif()
|
||||
if (LIBCXX_ENABLE_WERROR)
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -Werror)
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -WX)
|
||||
else()
|
||||
# TODO(EricWF) Remove this. We shouldn't be suppressing errors when -Werror is
|
||||
# added elsewhere.
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -Wno-error)
|
||||
endif()
|
||||
if (LIBCXX_ENABLE_PEDANTIC)
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE -pedantic)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Exception flags =============================================================
|
||||
function(cxx_add_exception_flags target)
|
||||
if (LIBCXX_ENABLE_EXCEPTIONS)
|
||||
# Catches C++ exceptions only and tells the compiler to assume that extern C
|
||||
# functions never throw a C++ exception.
|
||||
target_add_compile_flags_if_supported(${target} PUBLIC -EHsc)
|
||||
else()
|
||||
target_add_compile_flags_if_supported(${target} PUBLIC -EHs- -EHa-)
|
||||
target_add_compile_flags_if_supported(${target} PUBLIC -fno-exceptions)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# RTTI flags ==================================================================
|
||||
function(cxx_add_rtti_flags target)
|
||||
if (NOT LIBCXX_ENABLE_RTTI)
|
||||
target_add_compile_flags_if_supported(${target} PUBLIC -GR-)
|
||||
target_add_compile_flags_if_supported(${target} PUBLIC -fno-rtti)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Threading flags =============================================================
|
||||
if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY AND LIBCXX_ENABLE_SHARED)
|
||||
# Need to allow unresolved symbols if this is to work with shared library builds
|
||||
if (APPLE)
|
||||
add_link_flags("-undefined dynamic_lookup")
|
||||
else()
|
||||
# Relax this restriction from HandleLLVMOptions
|
||||
string(REPLACE "-Wl,-z,defs" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Assertion flags =============================================================
|
||||
define_if(LIBCXX_DEBUG_BUILD -D_DEBUG)
|
||||
if (LIBCXX_ENABLE_ASSERTIONS AND NOT LIBCXX_DEBUG_BUILD)
|
||||
# MSVC doesn't like _DEBUG on release builds. See PR 4379.
|
||||
define_if_not(LIBCXX_TARGETING_MSVC -D_DEBUG)
|
||||
endif()
|
||||
|
||||
# Modules flags ===============================================================
|
||||
# FIXME The libc++ sources are fundamentally non-modular. They need special
|
||||
# versions of the headers in order to provide C++03 and legacy ABI definitions.
|
||||
# NOTE: The public headers can be used with modules in all other contexts.
|
||||
function(cxx_add_module_flags target)
|
||||
if (LLVM_ENABLE_MODULES)
|
||||
# Ignore that the rest of the modules flags are now unused.
|
||||
target_add_compile_flags_if_supported(${target} PUBLIC -Wno-unused-command-line-argument)
|
||||
target_compile_options(${target} PUBLIC -fno-modules)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Sanitizer flags =============================================================
|
||||
|
||||
function(get_sanitizer_flags OUT_VAR USE_SANITIZER)
|
||||
set(SANITIZER_FLAGS)
|
||||
set(USE_SANITIZER "${USE_SANITIZER}")
|
||||
# NOTE: LLVM_USE_SANITIZER checks for a UNIX like system instead of MSVC.
|
||||
# But we don't have LLVM_ON_UNIX so checking for MSVC is the best we can do.
|
||||
if (USE_SANITIZER AND NOT MSVC)
|
||||
append_flags_if_supported(SANITIZER_FLAGS "-fno-omit-frame-pointer")
|
||||
append_flags_if_supported(SANITIZER_FLAGS "-gline-tables-only")
|
||||
|
||||
if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" AND
|
||||
NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELWITHDEBINFO")
|
||||
append_flags_if_supported(SANITIZER_FLAGS "-gline-tables-only")
|
||||
endif()
|
||||
if (USE_SANITIZER STREQUAL "Address")
|
||||
append_flags(SANITIZER_FLAGS "-fsanitize=address")
|
||||
elseif (USE_SANITIZER MATCHES "Memory(WithOrigins)?")
|
||||
append_flags(SANITIZER_FLAGS -fsanitize=memory)
|
||||
if (USE_SANITIZER STREQUAL "MemoryWithOrigins")
|
||||
append_flags(SANITIZER_FLAGS "-fsanitize-memory-track-origins")
|
||||
endif()
|
||||
elseif (USE_SANITIZER STREQUAL "Undefined")
|
||||
append_flags(SANITIZER_FLAGS "-fsanitize=undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all")
|
||||
elseif (USE_SANITIZER STREQUAL "Address;Undefined" OR
|
||||
USE_SANITIZER STREQUAL "Undefined;Address")
|
||||
append_flags(SANITIZER_FLAGS "-fsanitize=address,undefined -fno-sanitize=vptr,function -fno-sanitize-recover=all")
|
||||
elseif (USE_SANITIZER STREQUAL "Thread")
|
||||
append_flags(SANITIZER_FLAGS -fsanitize=thread)
|
||||
elseif (USE_SANITIZER STREQUAL "DataFlow")
|
||||
append_flags(SANITIZER_FLAGS -fsanitize=dataflow)
|
||||
else()
|
||||
message(WARNING "Unsupported value of LLVM_USE_SANITIZER: ${USE_SANITIZER}")
|
||||
endif()
|
||||
elseif(USE_SANITIZER AND MSVC)
|
||||
message(WARNING "LLVM_USE_SANITIZER is not supported on this platform.")
|
||||
endif()
|
||||
set(${OUT_VAR} "${SANITIZER_FLAGS}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
get_sanitizer_flags(SANITIZER_FLAGS "${LLVM_USE_SANITIZER}")
|
||||
|
||||
# Link system libraries =======================================================
|
||||
function(cxx_link_system_libraries target)
|
||||
|
||||
# In order to remove just libc++ from the link step
|
||||
# we need to use -nostdlib++ whenever it is supported.
|
||||
# Unfortunately this cannot be used universally because for example g++ supports
|
||||
# only -nodefaultlibs in which case all libraries will be removed and
|
||||
# all libraries but c++ have to be added in manually.
|
||||
if (CXX_SUPPORTS_NOSTDLIBXX_FLAG)
|
||||
target_add_link_flags_if_supported(${target} PRIVATE "-nostdlib++")
|
||||
else()
|
||||
target_add_link_flags_if_supported(${target} PRIVATE "-nodefaultlibs")
|
||||
target_add_compile_flags_if_supported(${target} PRIVATE "/Zl")
|
||||
target_add_link_flags_if_supported(${target} PRIVATE "/nodefaultlib")
|
||||
endif()
|
||||
|
||||
if (CXX_SUPPORTS_UNWINDLIB_EQ_NONE_FLAG AND LIBCXXABI_USE_LLVM_UNWINDER)
|
||||
# If we're linking directly against the libunwind that we're building
|
||||
# in the same invocation, don't try to link in the toolchain's
|
||||
# default libunwind (which may be missing still).
|
||||
target_add_link_flags_if_supported(${target} PRIVATE "--unwindlib=none")
|
||||
endif()
|
||||
|
||||
if (LIBCXX_HAS_SYSTEM_LIB)
|
||||
target_link_libraries(${target} PRIVATE System)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_HAS_PTHREAD_LIB)
|
||||
target_link_libraries(${target} PRIVATE pthread)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_HAS_C_LIB)
|
||||
target_link_libraries(${target} PRIVATE c)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_HAS_M_LIB)
|
||||
target_link_libraries(${target} PRIVATE m)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_HAS_RT_LIB)
|
||||
target_link_libraries(${target} PRIVATE rt)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_USE_COMPILER_RT)
|
||||
find_compiler_rt_library(builtins LIBCXX_BUILTINS_LIBRARY)
|
||||
if (LIBCXX_BUILTINS_LIBRARY)
|
||||
target_link_libraries(${target} PRIVATE "${LIBCXX_BUILTINS_LIBRARY}")
|
||||
endif()
|
||||
elseif (LIBCXX_HAS_GCC_LIB)
|
||||
target_link_libraries(${target} PRIVATE gcc)
|
||||
elseif (LIBCXX_HAS_GCC_S_LIB)
|
||||
target_link_libraries(${target} PRIVATE gcc_s)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_HAS_ATOMIC_LIB)
|
||||
target_link_libraries(${target} PRIVATE atomic)
|
||||
endif()
|
||||
|
||||
if (MINGW)
|
||||
target_link_libraries(${target} PRIVATE "${MINGW_LIBRARIES}")
|
||||
endif()
|
||||
|
||||
if (LIBCXX_TARGETING_MSVC)
|
||||
if (LIBCXX_DEBUG_BUILD)
|
||||
set(LIB_SUFFIX "d")
|
||||
else()
|
||||
set(LIB_SUFFIX "")
|
||||
endif()
|
||||
|
||||
target_link_libraries(${target} PRIVATE ucrt${LIB_SUFFIX}) # Universal C runtime
|
||||
target_link_libraries(${target} PRIVATE vcruntime${LIB_SUFFIX}) # C++ runtime
|
||||
target_link_libraries(${target} PRIVATE msvcrt${LIB_SUFFIX}) # C runtime startup files
|
||||
target_link_libraries(${target} PRIVATE msvcprt${LIB_SUFFIX}) # C++ standard library. Required for exception_ptr internals.
|
||||
# Required for standards-complaint wide character formatting functions
|
||||
# (e.g. `printfw`/`scanfw`)
|
||||
target_link_libraries(${target} PRIVATE iso_stdio_wide_specifiers)
|
||||
endif()
|
||||
|
||||
if (ANDROID AND ANDROID_PLATFORM_LEVEL LESS 21)
|
||||
target_link_libraries(${target} PUBLIC android_support)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Windows-related flags =======================================================
|
||||
function(cxx_add_windows_flags target)
|
||||
if(WIN32 AND NOT MINGW)
|
||||
target_compile_definitions(${target} PRIVATE
|
||||
# Ignore the -MSC_VER mismatch, as we may build
|
||||
# with a different compatibility version.
|
||||
_ALLOW_MSC_VER_MISMATCH
|
||||
# Don't check the msvcprt iterator debug levels
|
||||
# as we will define the iterator types; libc++
|
||||
# uses a different macro to identify the debug
|
||||
# level.
|
||||
_ALLOW_ITERATOR_DEBUG_LEVEL_MISMATCH
|
||||
# We are building the c++ runtime, don't pull in
|
||||
# msvcprt.
|
||||
_CRTBLD
|
||||
# Don't warn on the use of "deprecated"
|
||||
# "insecure" functions which are standards
|
||||
# specified.
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
# Use the ISO conforming behaviour for conversion
|
||||
# in printf, scanf.
|
||||
_CRT_STDIO_ISO_WIDE_SPECIFIERS)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Configuration file flags =====================================================
|
||||
config_define(${LIBCXX_ABI_VERSION} _LIBCPP_ABI_VERSION)
|
||||
config_define(${LIBCXX_ABI_NAMESPACE} _LIBCPP_ABI_NAMESPACE)
|
||||
config_define_if(LIBCXX_ABI_FORCE_ITANIUM _LIBCPP_ABI_FORCE_ITANIUM)
|
||||
config_define_if(LIBCXX_ABI_FORCE_MICROSOFT _LIBCPP_ABI_FORCE_MICROSOFT)
|
||||
config_define_if_not(LIBCXX_ENABLE_THREADS _LIBCPP_HAS_NO_THREADS)
|
||||
config_define_if_not(LIBCXX_ENABLE_MONOTONIC_CLOCK _LIBCPP_HAS_NO_MONOTONIC_CLOCK)
|
||||
if (NOT LIBCXX_TYPEINFO_COMPARISON_IMPLEMENTATION STREQUAL "default")
|
||||
config_define("${LIBCXX_TYPEINFO_COMPARISON_IMPLEMENTATION}" _LIBCPP_TYPEINFO_COMPARISON_IMPLEMENTATION)
|
||||
endif()
|
||||
config_define_if(LIBCXX_HAS_PTHREAD_API _LIBCPP_HAS_THREAD_API_PTHREAD)
|
||||
config_define_if(LIBCXX_HAS_EXTERNAL_THREAD_API _LIBCPP_HAS_THREAD_API_EXTERNAL)
|
||||
config_define_if(LIBCXX_HAS_WIN32_THREAD_API _LIBCPP_HAS_THREAD_API_WIN32)
|
||||
config_define_if(LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY _LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL)
|
||||
config_define_if(LIBCXX_HAS_MUSL_LIBC _LIBCPP_HAS_MUSL_LIBC)
|
||||
config_define_if(LIBCXX_NO_VCRUNTIME _LIBCPP_NO_VCRUNTIME)
|
||||
config_define_if(LIBCXX_ENABLE_PARALLEL_ALGORITHMS _LIBCPP_HAS_PARALLEL_ALGORITHMS)
|
||||
config_define_if_not(LIBCXX_ENABLE_FILESYSTEM _LIBCPP_HAS_NO_FILESYSTEM_LIBRARY)
|
||||
config_define_if_not(LIBCXX_ENABLE_RANDOM_DEVICE _LIBCPP_HAS_NO_RANDOM_DEVICE)
|
||||
config_define_if_not(LIBCXX_ENABLE_LOCALIZATION _LIBCPP_HAS_NO_LOCALIZATION)
|
||||
config_define_if_not(LIBCXX_ENABLE_UNICODE _LIBCPP_HAS_NO_UNICODE)
|
||||
config_define_if_not(LIBCXX_ENABLE_WIDE_CHARACTERS _LIBCPP_HAS_NO_WIDE_CHARACTERS)
|
||||
config_define_if_not(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS _LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS)
|
||||
config_define_if(LIBCXX_ENABLE_DEBUG_MODE _LIBCPP_ENABLE_DEBUG_MODE)
|
||||
if (LIBCXX_ENABLE_ASSERTIONS)
|
||||
config_define(1 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT)
|
||||
else()
|
||||
config_define(0 _LIBCPP_ENABLE_ASSERTIONS_DEFAULT)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_ABI_DEFINES)
|
||||
set(abi_defines)
|
||||
foreach (abi_define ${LIBCXX_ABI_DEFINES})
|
||||
if (NOT abi_define MATCHES "^_LIBCPP_ABI_")
|
||||
message(SEND_ERROR "Invalid ABI macro ${abi_define} in LIBCXX_ABI_DEFINES")
|
||||
endif()
|
||||
list(APPEND abi_defines "#define ${abi_define}")
|
||||
endforeach()
|
||||
string(REPLACE ";" "\n" abi_defines "${abi_defines}")
|
||||
config_define(${abi_defines} _LIBCPP_ABI_DEFINES)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_EXTRA_SITE_DEFINES)
|
||||
set(extra_site_defines)
|
||||
foreach (extra_site_define ${LIBCXX_EXTRA_SITE_DEFINES})
|
||||
# Allow defines such as DEFINE=VAL, transformed into "#define DEFINE VAL".
|
||||
string(REPLACE "=" " " extra_site_define "${extra_site_define}")
|
||||
list(APPEND extra_site_defines "#define ${extra_site_define}")
|
||||
endforeach()
|
||||
string(REPLACE ";" "\n" extra_site_defines "${extra_site_defines}")
|
||||
config_define(${extra_site_defines} _LIBCPP_EXTRA_SITE_DEFINES)
|
||||
endif()
|
||||
|
||||
# By default libc++ on Windows expects to use a shared library, which requires
|
||||
# the headers to use DLL import/export semantics. However when building a
|
||||
# static library only we modify the headers to disable DLL import/export.
|
||||
if (DEFINED WIN32 AND LIBCXX_ENABLE_STATIC AND NOT LIBCXX_ENABLE_SHARED)
|
||||
message(STATUS "Generating custom __config for non-DLL Windows build")
|
||||
config_define(ON _LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
endif()
|
||||
|
||||
if (WIN32 AND LIBCXX_ENABLE_STATIC_ABI_LIBRARY)
|
||||
# If linking libcxxabi statically into libcxx, skip the dllimport attributes
|
||||
# on symbols we refer to from libcxxabi.
|
||||
add_definitions(-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS)
|
||||
endif()
|
||||
|
||||
# Setup all common build flags =================================================
|
||||
function(cxx_add_common_build_flags target)
|
||||
cxx_add_basic_build_flags(${target})
|
||||
cxx_add_warning_flags(${target})
|
||||
cxx_add_windows_flags(${target})
|
||||
cxx_add_exception_flags(${target})
|
||||
cxx_add_rtti_flags(${target})
|
||||
cxx_add_module_flags(${target})
|
||||
cxx_link_system_libraries(${target})
|
||||
endfunction()
|
||||
|
||||
#===============================================================================
|
||||
# Setup Source Code And Tests
|
||||
#===============================================================================
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(utils)
|
||||
|
||||
set(LIBCXX_TEST_DEPS "cxx_experimental")
|
||||
|
||||
if (LIBCXX_BUILD_EXTERNAL_THREAD_LIBRARY)
|
||||
list(APPEND LIBCXX_TEST_DEPS cxx_external_threads)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_INCLUDE_BENCHMARKS)
|
||||
add_subdirectory(benchmarks)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_INCLUDE_TESTS)
|
||||
add_subdirectory(test)
|
||||
add_subdirectory(lib/abi)
|
||||
endif()
|
||||
|
||||
if (LIBCXX_INCLUDE_DOCS)
|
||||
add_subdirectory(docs)
|
||||
endif()
|
@ -1,186 +0,0 @@
|
||||
This file is a partial list of people who have contributed to the LLVM/libc++
|
||||
project. If you have contributed a patch or made some other contribution to
|
||||
LLVM/libc++, please submit a patch to this file to add yourself, and it will be
|
||||
done!
|
||||
|
||||
The list is sorted by surname and formatted to allow easy grepping and
|
||||
beautification by scripts. The fields are: name (N), email (E), web-address
|
||||
(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
|
||||
(S).
|
||||
|
||||
N: Saleem Abdulrasool
|
||||
E: compnerd@compnerd.org
|
||||
D: Minor patches and Linux fixes.
|
||||
|
||||
N: Ulf Adams
|
||||
D: Invented the Ryu and Ryu Printf algorithms used in floating-point to_chars, and wrote the initial code.
|
||||
|
||||
N: Muiez Ahmed
|
||||
E: muiez@ibm.com
|
||||
D: z/OS port.
|
||||
|
||||
N: Dan Albert
|
||||
E: danalbert@google.com
|
||||
D: Android support and test runner improvements.
|
||||
|
||||
N: Dimitry Andric
|
||||
E: dimitry@andric.com
|
||||
D: Visibility fixes, minor FreeBSD portability patches.
|
||||
|
||||
N: Holger Arnold
|
||||
E: holgerar@gmail.com
|
||||
D: Minor fix.
|
||||
|
||||
N: Jorg Brown
|
||||
D: Ported floating-point to_chars from MSVC to libc++.
|
||||
|
||||
N: David Chisnall
|
||||
E: theraven at theravensnest dot org
|
||||
D: FreeBSD and Solaris ports, libcxxrt support, some atomics work.
|
||||
|
||||
N: Marshall Clow
|
||||
E: mclow.lists@gmail.com
|
||||
E: marshall@idio.com
|
||||
D: C++14 support, patches and bug fixes.
|
||||
|
||||
N: Jonathan B Coe
|
||||
E: jbcoe@me.com
|
||||
D: Implementation of propagate_const.
|
||||
|
||||
N: Matthew Dempsky
|
||||
E: matthew@dempsky.org
|
||||
D: Minor patches and bug fixes.
|
||||
|
||||
N: Christopher Di Bella
|
||||
E: cjdb@google.com
|
||||
E: cjdb.ns@gmail.com
|
||||
D: Library concepts.
|
||||
|
||||
N: Glen Joseph Fernandes
|
||||
E: glenjofe@gmail.com
|
||||
D: Implementation of to_address.
|
||||
|
||||
N: Eric Fiselier
|
||||
E: eric@efcs.ca
|
||||
D: LFTS support, patches and bug fixes.
|
||||
|
||||
N: Bill Fisher
|
||||
E: william.w.fisher@gmail.com
|
||||
D: Regex bug fixes.
|
||||
|
||||
N: Google Inc.
|
||||
D: Copyright owner and contributor of the CityHash algorithm
|
||||
|
||||
N: Howard Hinnant
|
||||
E: hhinnant@apple.com
|
||||
D: Architect and primary author of libc++
|
||||
|
||||
N: Sergej Jaskiewicz
|
||||
E: jaskiewiczs@icloud.com
|
||||
D: Minor improvements in the testing infrastructure
|
||||
|
||||
N: Hyeon-bin Jeong
|
||||
E: tuhertz@gmail.com
|
||||
D: Minor patches and bug fixes.
|
||||
|
||||
N: Argyrios Kyrtzidis
|
||||
E: kyrtzidis@apple.com
|
||||
D: Bug fixes.
|
||||
|
||||
N: Stephan T. Lavavej
|
||||
E: stl@microsoft.com
|
||||
E: stl@nuwen.net
|
||||
D: Implemented floating-point to_chars.
|
||||
|
||||
N: Microsoft Corporation
|
||||
D: Contributed floating-point to_chars.
|
||||
|
||||
N: Bruce Mitchener, Jr.
|
||||
E: bruce.mitchener@gmail.com
|
||||
D: Emscripten-related changes.
|
||||
|
||||
N: Michel Morin
|
||||
E: mimomorin@gmail.com
|
||||
D: Minor patches to is_convertible.
|
||||
|
||||
N: Andrew Morrow
|
||||
E: andrew.c.morrow@gmail.com
|
||||
D: Minor patches and Linux fixes.
|
||||
|
||||
N: Michael Park
|
||||
E: mcypark@gmail.com
|
||||
D: Implementation of <variant>.
|
||||
|
||||
N: Arvid Picciani
|
||||
E: aep at exys dot org
|
||||
D: Minor patches and musl port.
|
||||
|
||||
N: Bjorn Reese
|
||||
E: breese@users.sourceforge.net
|
||||
D: Initial regex prototype
|
||||
|
||||
N: Nico Rieck
|
||||
E: nico.rieck@gmail.com
|
||||
D: Windows fixes
|
||||
|
||||
N: Jon Roelofs
|
||||
E: jroelofS@jroelofs.com
|
||||
D: Remote testing, Newlib port, baremetal/single-threaded support.
|
||||
|
||||
N: Kent Ross
|
||||
E: k@mad.cash
|
||||
D: Patches for operator<=> support
|
||||
|
||||
N: Jonathan Sauer
|
||||
D: Minor patches, mostly related to constexpr
|
||||
|
||||
N: Craig Silverstein
|
||||
E: csilvers@google.com
|
||||
D: Implemented Cityhash as the string hash function on 64-bit machines
|
||||
|
||||
N: Richard Smith
|
||||
D: Minor patches.
|
||||
|
||||
N: Joerg Sonnenberger
|
||||
E: joerg@NetBSD.org
|
||||
D: NetBSD port.
|
||||
|
||||
N: Stephan Tolksdorf
|
||||
E: st@quanttec.com
|
||||
D: Minor <atomic> fix
|
||||
|
||||
N: Ruben Van Boxem
|
||||
E: vanboxem dot ruben at gmail dot com
|
||||
D: Initial Windows patches.
|
||||
|
||||
N: Michael van der Westhuizen
|
||||
E: r1mikey at gmail dot com
|
||||
|
||||
N: Larisse Voufo
|
||||
D: Minor patches.
|
||||
|
||||
N: Klaas de Vries
|
||||
E: klaas at klaasgaaf dot nl
|
||||
D: Minor bug fix.
|
||||
|
||||
N: Mark de Wever
|
||||
E: koraq at xs4all dot nl
|
||||
D: Format library support.
|
||||
D: Finalized the porting of MSVC's to_chars to libc++.
|
||||
|
||||
N: Zhang Xiongpang
|
||||
E: zhangxiongpang@gmail.com
|
||||
D: Minor patches and bug fixes.
|
||||
|
||||
N: Xing Xue
|
||||
E: xingxue@ca.ibm.com
|
||||
D: AIX port
|
||||
|
||||
N: Jeffrey Yasskin
|
||||
E: jyasskin@gmail.com
|
||||
E: jyasskin@google.com
|
||||
D: Linux fixes.
|
||||
|
||||
N: Zhihao Yuan
|
||||
E: lichray@gmail.com
|
||||
D: Standard compatibility fixes.
|
@ -1,311 +0,0 @@
|
||||
==============================================================================
|
||||
The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
|
||||
==============================================================================
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
---- LLVM Exceptions to the Apache 2.0 License ----
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into an Object form of such source code, you
|
||||
may redistribute such embedded portions in such Object form without complying
|
||||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision (Section
|
||||
3), the indemnity provision (Section 9) or other Section of the License
|
||||
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||
the License, but only in their entirety and only with respect to the Combined
|
||||
Software.
|
||||
|
||||
==============================================================================
|
||||
Software from third parties included in the LLVM Project:
|
||||
==============================================================================
|
||||
The LLVM Project contains third party software which is under different license
|
||||
terms. All such code will be identified clearly using at least one of two
|
||||
mechanisms:
|
||||
1) It will be in a separate directory tree with its own `LICENSE.txt` or
|
||||
`LICENSE` file at the top containing the specific license and restrictions
|
||||
which apply to that software, or
|
||||
2) It will contain specific license and restriction terms at the top of every
|
||||
file.
|
||||
|
||||
==============================================================================
|
||||
Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
|
||||
==============================================================================
|
||||
|
||||
The libc++ library is dual licensed under both the University of Illinois
|
||||
"BSD-Like" license and the MIT license. As a user of this code you may choose
|
||||
to use it under either license. As a contributor, you agree to allow your code
|
||||
to be used under both.
|
||||
|
||||
Full text of the relevant licenses is included below.
|
||||
|
||||
==============================================================================
|
||||
|
||||
University of Illinois/NCSA
|
||||
Open Source License
|
||||
|
||||
Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Developed by:
|
||||
|
||||
LLVM Team
|
||||
|
||||
University of Illinois at Urbana-Champaign
|
||||
|
||||
http://llvm.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal with
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimers.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimers in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the names of the LLVM Team, University of Illinois at
|
||||
Urbana-Champaign, nor the names of its contributors may be used to
|
||||
endorse or promote products derived from this Software without specific
|
||||
prior written permission.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
|
||||
Copyright (c) 2009-2014 by the contributors listed in CREDITS.TXT
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
@ -1,5 +0,0 @@
|
||||
## libc++
|
||||
|
||||
LLVM libc++, specifically for Android, removing exception and RTTI support.
|
||||
|
||||
Source code is extracted from both the upstrean and AOSP `llvm-project` repository.
|
@ -1,23 +0,0 @@
|
||||
This is meant to be a general place to list things that should be done "someday"
|
||||
|
||||
CXX Runtime Library Tasks
|
||||
=========================
|
||||
* Look into mirroring libsupc++'s typeinfo vtable layout when libsupc++/libstdc++
|
||||
is used as the runtime library.
|
||||
* Investigate and document interoperability between libc++ and libstdc++ on
|
||||
linux. Do this for every supported c++ runtime library.
|
||||
|
||||
Atomic Related Tasks
|
||||
====================
|
||||
* future should use <atomic> for synchronization.
|
||||
|
||||
Test Suite Tasks
|
||||
================
|
||||
* Improve the quality and portability of the locale test data.
|
||||
* Convert failure tests to use Clang Verify.
|
||||
|
||||
Misc Tasks
|
||||
==========
|
||||
* Find all sequences of >2 underscores and eradicate them.
|
||||
* run clang-tidy on libc++
|
||||
* Document the "conditionally-supported" bits of libc++
|
@ -1,53 +0,0 @@
|
||||
@echo on
|
||||
|
||||
if NOT EXIST C:\projects\deps (
|
||||
mkdir C:\projects\deps
|
||||
)
|
||||
cd C:\projects\deps
|
||||
|
||||
::###########################################################################
|
||||
:: Setup Compiler
|
||||
::###########################################################################
|
||||
if NOT EXIST llvm-installer.exe (
|
||||
appveyor DownloadFile https://prereleases.llvm.org/win-snapshots/LLVM-9.0.0-r357435-win32.exe -FileName llvm-installer.exe
|
||||
)
|
||||
if "%CLANG_VERSION%"=="ToT" (
|
||||
START /WAIT llvm-installer.exe /S /D=C:\"Program Files\LLVM"
|
||||
)
|
||||
if DEFINED CLANG_VERSION @set PATH="C:\Program Files\LLVM\bin";%PATH%
|
||||
if DEFINED CLANG_VERSION clang-cl -v
|
||||
|
||||
if DEFINED MINGW_PATH rename "C:\Program Files\Git\usr\bin\sh.exe" "sh-ignored.exe"
|
||||
if DEFINED MINGW_PATH @set "PATH=%PATH:C:\Program Files (x86)\Git\bin=%"
|
||||
if DEFINED MINGW_PATH @set "PATH=%PATH%;%MINGW_PATH%"
|
||||
if DEFINED MINGW_PATH g++ -v
|
||||
|
||||
::###########################################################################
|
||||
:: Install a recent CMake
|
||||
::###########################################################################
|
||||
if NOT EXIST cmake (
|
||||
appveyor DownloadFile https://cmake.org/files/v3.7/cmake-3.7.2-win64-x64.zip -FileName cmake.zip
|
||||
7z x cmake.zip -oC:\projects\deps > nul
|
||||
move C:\projects\deps\cmake-* C:\projects\deps\cmake
|
||||
rm cmake.zip
|
||||
)
|
||||
@set PATH=C:\projects\deps\cmake\bin;%PATH%
|
||||
cmake --version
|
||||
|
||||
::###########################################################################
|
||||
:: Install Ninja
|
||||
::###########################################################################
|
||||
if NOT EXIST ninja (
|
||||
appveyor DownloadFile https://github.com/ninja-build/ninja/releases/download/v1.6.0/ninja-win.zip -FileName ninja.zip
|
||||
7z x ninja.zip -oC:\projects\deps\ninja > nul
|
||||
rm ninja.zip
|
||||
)
|
||||
@set PATH=C:\projects\deps\ninja;%PATH%
|
||||
ninja --version
|
||||
|
||||
::###########################################################################
|
||||
:: Setup the cached copy of LLVM
|
||||
::###########################################################################
|
||||
git clone --depth=1 http://llvm.org/git/llvm.git
|
||||
|
||||
@echo off
|
@ -1,71 +0,0 @@
|
||||
version: '{build}'
|
||||
|
||||
shallow_clone: true
|
||||
|
||||
build:
|
||||
verbosity: detailed
|
||||
|
||||
configuration:
|
||||
- Debug
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_OPTIONS: -DCMAKE_C_COMPILER=clang-cl.exe -DCMAKE_CXX_COMPILER=clang-cl.exe
|
||||
CLANG_VERSION: ToT
|
||||
MSVC_SETUP_PATH: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat
|
||||
MSVC_SETUP_ARG: x86
|
||||
GENERATOR: Ninja
|
||||
MAKE_PROGRAM: ninja
|
||||
APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
# TODO: Maybe re-enable this configuration? Do we want to support MSVC 2015's runtime?
|
||||
# - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
# MINGW_PATH: C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin
|
||||
# GENERATOR: MinGW Makefiles
|
||||
# MAKE_PROGRAM: mingw32-make
|
||||
# APPVEYOR_SAVE_CACHE_ON_ERROR: true
|
||||
|
||||
install:
|
||||
############################################################################
|
||||
# All external dependencies are installed in C:\projects\deps
|
||||
############################################################################
|
||||
- call "%APPVEYOR_BUILD_FOLDER%\\appveyor-reqs-install.cmd"
|
||||
|
||||
before_build:
|
||||
- if DEFINED MSVC_SETUP_PATH call "%MSVC_SETUP_PATH%" %MSVC_SETUP_ARG%
|
||||
- cd %APPVEYOR_BUILD_FOLDER%
|
||||
|
||||
build_script:
|
||||
- md C:\projects\build-libcxx
|
||||
- cd C:\projects\build-libcxx
|
||||
- echo %configuration%
|
||||
|
||||
#############################################################################
|
||||
# Configuration Step
|
||||
#############################################################################
|
||||
- cmake -G "%GENERATOR%" %CMAKE_OPTIONS%
|
||||
"-DCMAKE_BUILD_TYPE=%configuration%"
|
||||
"-DLLVM_PATH=C:\projects\deps\llvm"
|
||||
-DLLVM_LIT_ARGS="-sv --show-xfail --show-unsupported"
|
||||
%APPVEYOR_BUILD_FOLDER%
|
||||
|
||||
#############################################################################
|
||||
# Build Step
|
||||
#############################################################################
|
||||
- "%MAKE_PROGRAM%"
|
||||
|
||||
test_script:
|
||||
- "%MAKE_PROGRAM% check-cxx"
|
||||
|
||||
on_failure:
|
||||
- appveyor PushArtifact CMakeFiles/CMakeOutput.log
|
||||
- appveyor PushArtifact CMakeFiles/CMakeError.log
|
||||
|
||||
artifacts:
|
||||
- path: '_build/CMakeFiles/*.log'
|
||||
name: logs
|
||||
|
||||
cache:
|
||||
- C:\projects\deps\ninja
|
||||
- C:\projects\deps\cmake
|
||||
- C:\projects\deps\llvm-installer.exe
|
@ -1,233 +0,0 @@
|
||||
if (CMAKE_VERSION VERSION_LESS 3.17)
|
||||
message(WARNING "The libc++ benchmarks won't be available because the version of CMake is too old to support them.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(ExternalProject)
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
#==============================================================================
|
||||
# Build Google Benchmark for libc++
|
||||
#==============================================================================
|
||||
|
||||
set(CMAKE_FOLDER "${CMAKE_FOLDER}/Benchmarks")
|
||||
|
||||
set(BENCHMARK_LIBCXX_COMPILE_FLAGS
|
||||
-Wno-unused-command-line-argument
|
||||
-nostdinc++
|
||||
-isystem "${LIBCXX_GENERATED_INCLUDE_DIR}"
|
||||
-L${LIBCXX_LIBRARY_DIR}
|
||||
-Wl,-rpath,${LIBCXX_LIBRARY_DIR}
|
||||
${SANITIZER_FLAGS}
|
||||
)
|
||||
if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
|
||||
list(APPEND BENCHMARK_LIBCXX_COMPILE_FLAGS
|
||||
-isystem "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}")
|
||||
endif()
|
||||
if (DEFINED LIBCXX_CXX_ABI_LIBRARY_PATH)
|
||||
list(APPEND BENCHMARK_LIBCXX_COMPILE_FLAGS
|
||||
-L${LIBCXX_CXX_ABI_LIBRARY_PATH}
|
||||
-Wl,-rpath,${LIBCXX_CXX_ABI_LIBRARY_PATH})
|
||||
endif()
|
||||
split_list(BENCHMARK_LIBCXX_COMPILE_FLAGS)
|
||||
|
||||
ExternalProject_Add(google-benchmark-libcxx
|
||||
EXCLUDE_FROM_ALL ON
|
||||
DEPENDS cxx cxx-headers
|
||||
PREFIX benchmark-libcxx
|
||||
SOURCE_DIR ${LLVM_THIRD_PARTY_DIR}/benchmark
|
||||
INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/benchmark-libcxx
|
||||
CMAKE_CACHE_ARGS
|
||||
-DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_BUILD_TYPE:STRING=RELEASE
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
-DCMAKE_CXX_FLAGS:STRING=${BENCHMARK_LIBCXX_COMPILE_FLAGS}
|
||||
-DBENCHMARK_USE_LIBCXX:BOOL=ON
|
||||
-DBENCHMARK_ENABLE_TESTING:BOOL=OFF)
|
||||
|
||||
#==============================================================================
|
||||
# Build Google Benchmark for the native stdlib
|
||||
#==============================================================================
|
||||
set(BENCHMARK_NATIVE_TARGET_FLAGS)
|
||||
if (LIBCXX_BENCHMARK_NATIVE_GCC_TOOLCHAIN)
|
||||
set(BENCHMARK_NATIVE_TARGET_FLAGS
|
||||
--gcc-toolchain=${LIBCXX_BENCHMARK_NATIVE_GCC_TOOLCHAIN})
|
||||
endif()
|
||||
split_list(BENCHMARK_NATIVE_TARGET_FLAGS)
|
||||
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB)
|
||||
ExternalProject_Add(google-benchmark-native
|
||||
EXCLUDE_FROM_ALL ON
|
||||
PREFIX benchmark-native
|
||||
SOURCE_DIR ${LLVM_THIRD_PARTY_DIR}/benchmark
|
||||
INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/benchmark-native
|
||||
CMAKE_CACHE_ARGS
|
||||
-DCMAKE_C_COMPILER:STRING=${CMAKE_C_COMPILER}
|
||||
-DCMAKE_CXX_COMPILER:STRING=${CMAKE_CXX_COMPILER}
|
||||
-DCMAKE_CXX_FLAGS:STRING=${BENCHMARK_NATIVE_TARGET_FLAGS}
|
||||
-DCMAKE_BUILD_TYPE:STRING=RELEASE
|
||||
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||
-DBENCHMARK_ENABLE_TESTING:BOOL=OFF)
|
||||
endif()
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Benchmark tests configuration
|
||||
#==============================================================================
|
||||
add_custom_target(cxx-benchmarks)
|
||||
set(BENCHMARK_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(BENCHMARK_LIBCXX_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/benchmark-libcxx)
|
||||
set(BENCHMARK_NATIVE_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/benchmark-native)
|
||||
|
||||
add_library( cxx-benchmarks-flags INTERFACE)
|
||||
target_compile_features( cxx-benchmarks-flags INTERFACE cxx_std_20)
|
||||
target_compile_options( cxx-benchmarks-flags INTERFACE -fsized-deallocation -nostdinc++)
|
||||
target_include_directories(cxx-benchmarks-flags INTERFACE "${LIBCXX_GENERATED_INCLUDE_DIR}"
|
||||
INTERFACE "${BENCHMARK_LIBCXX_INSTALL}/include"
|
||||
INTERFACE "${LIBCXX_SOURCE_DIR}/test/support")
|
||||
|
||||
add_library( cxx-benchmarks-flags-native INTERFACE)
|
||||
target_link_libraries( cxx-benchmarks-flags-native INTERFACE cxx-benchmarks-flags)
|
||||
target_compile_options(cxx-benchmarks-flags-native INTERFACE ${BENCHMARK_NATIVE_TARGET_FLAGS})
|
||||
target_link_options( cxx-benchmarks-flags-native INTERFACE ${BENCHMARK_NATIVE_TARGET_FLAGS} "-L${BENCHMARK_NATIVE_INSTALL}/lib")
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB STREQUAL "libstdc++")
|
||||
find_library(LIBSTDCXX_FILESYSTEM_TEST stdc++fs
|
||||
PATHS ${LIBCXX_BENCHMARK_NATIVE_GCC_TOOLCHAIN}
|
||||
PATH_SUFFIXES lib lib64
|
||||
DOC "The libstdc++ filesystem library used by the benchmarks"
|
||||
)
|
||||
if (LIBSTDCXX_FILESYSTEM_TEST)
|
||||
target_link_libraries(cxx-benchmarks-flags-native INTERFACE -lstdc++fs)
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(cxx-benchmarks-flags-native INTERFACE -lc++fs -lc++experimental)
|
||||
endif()
|
||||
|
||||
add_library( cxx-benchmarks-flags-libcxx INTERFACE)
|
||||
target_link_libraries( cxx-benchmarks-flags-libcxx INTERFACE cxx-benchmarks-flags)
|
||||
target_compile_options(cxx-benchmarks-flags-libcxx INTERFACE ${SANITIZER_FLAGS} -Wno-user-defined-literals -Wno-suggest-override)
|
||||
target_link_options( cxx-benchmarks-flags-libcxx INTERFACE -nodefaultlibs "-L${BENCHMARK_LIBCXX_INSTALL}/lib" ${SANITIZER_FLAGS})
|
||||
|
||||
set(libcxx_benchmark_targets)
|
||||
|
||||
function(add_benchmark_test name source_file)
|
||||
set(libcxx_target ${name}_libcxx)
|
||||
list(APPEND libcxx_benchmark_targets ${libcxx_target})
|
||||
add_executable(${libcxx_target} EXCLUDE_FROM_ALL ${source_file})
|
||||
target_link_libraries(${libcxx_target} PRIVATE cxx-benchmarks-flags-libcxx)
|
||||
add_dependencies(${libcxx_target} cxx google-benchmark-libcxx)
|
||||
add_dependencies(cxx-benchmarks ${libcxx_target})
|
||||
if (LIBCXX_ENABLE_SHARED)
|
||||
target_link_libraries(${libcxx_target} PRIVATE cxx_shared)
|
||||
else()
|
||||
target_link_libraries(${libcxx_target} PRIVATE cxx_static)
|
||||
endif()
|
||||
target_link_libraries(${libcxx_target} PRIVATE cxx_experimental benchmark)
|
||||
if (LLVM_USE_SANITIZER)
|
||||
target_link_libraries(${libcxx_target} PRIVATE -ldl)
|
||||
endif()
|
||||
set_target_properties(${libcxx_target}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "${name}.libcxx.out"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${BENCHMARK_OUTPUT_DIR}"
|
||||
CXX_EXTENSIONS NO)
|
||||
cxx_link_system_libraries(${libcxx_target})
|
||||
if (LIBCXX_BENCHMARK_NATIVE_STDLIB)
|
||||
set(native_target ${name}_native)
|
||||
add_executable(${native_target} EXCLUDE_FROM_ALL ${source_file})
|
||||
target_link_libraries(${native_target} PRIVATE cxx-benchmarks-flags-native)
|
||||
add_dependencies(${native_target} google-benchmark-native
|
||||
google-benchmark-libcxx)
|
||||
target_link_libraries(${native_target} PRIVATE -lbenchmark)
|
||||
if (LIBCXX_HAS_PTHREAD_LIB)
|
||||
target_link_libraries(${native_target} PRIVATE -pthread)
|
||||
endif()
|
||||
add_dependencies(cxx-benchmarks ${native_target})
|
||||
set_target_properties(${native_target}
|
||||
PROPERTIES
|
||||
OUTPUT_NAME "${name}.native.out"
|
||||
RUNTIME_OUTPUT_DIRECTORY "${BENCHMARK_OUTPUT_DIR}"
|
||||
CXX_EXTENSIONS NO)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
|
||||
#==============================================================================
|
||||
# Register Benchmark tests
|
||||
#==============================================================================
|
||||
set(BENCHMARK_TESTS
|
||||
algorithms.partition_point.bench.cpp
|
||||
algorithms/lower_bound.bench.cpp
|
||||
algorithms/make_heap.bench.cpp
|
||||
algorithms/make_heap_then_sort_heap.bench.cpp
|
||||
algorithms/min_max_element.bench.cpp
|
||||
algorithms/pop_heap.bench.cpp
|
||||
algorithms/push_heap.bench.cpp
|
||||
algorithms/ranges_make_heap.bench.cpp
|
||||
algorithms/ranges_make_heap_then_sort_heap.bench.cpp
|
||||
algorithms/ranges_pop_heap.bench.cpp
|
||||
algorithms/ranges_push_heap.bench.cpp
|
||||
algorithms/ranges_sort.bench.cpp
|
||||
algorithms/ranges_sort_heap.bench.cpp
|
||||
algorithms/ranges_stable_sort.bench.cpp
|
||||
algorithms/sort.bench.cpp
|
||||
algorithms/sort_heap.bench.cpp
|
||||
algorithms/stable_sort.bench.cpp
|
||||
allocation.bench.cpp
|
||||
deque.bench.cpp
|
||||
deque_iterator.bench.cpp
|
||||
filesystem.bench.cpp
|
||||
format_to_n.bench.cpp
|
||||
format_to.bench.cpp
|
||||
format.bench.cpp
|
||||
formatted_size.bench.cpp
|
||||
formatter_float.bench.cpp
|
||||
formatter_int.bench.cpp
|
||||
function.bench.cpp
|
||||
join_view.bench.cpp
|
||||
map.bench.cpp
|
||||
monotonic_buffer.bench.cpp
|
||||
ordered_set.bench.cpp
|
||||
std_format_spec_string_unicode.bench.cpp
|
||||
string.bench.cpp
|
||||
stringstream.bench.cpp
|
||||
to_chars.bench.cpp
|
||||
unordered_set_operations.bench.cpp
|
||||
util_smartptr.bench.cpp
|
||||
variant_visit_1.bench.cpp
|
||||
variant_visit_2.bench.cpp
|
||||
variant_visit_3.bench.cpp
|
||||
vector_operations.bench.cpp
|
||||
)
|
||||
|
||||
foreach(test_path ${BENCHMARK_TESTS})
|
||||
get_filename_component(test_file "${test_path}" NAME)
|
||||
string(REPLACE ".bench.cpp" "" test_name "${test_file}")
|
||||
if (NOT DEFINED ${test_name}_REPORTED)
|
||||
message(STATUS "Adding Benchmark: ${test_file}")
|
||||
# Only report the adding of the benchmark once.
|
||||
set(${test_name}_REPORTED ON CACHE INTERNAL "")
|
||||
endif()
|
||||
add_benchmark_test(${test_name} ${test_path})
|
||||
endforeach()
|
||||
|
||||
if (LIBCXX_INCLUDE_TESTS)
|
||||
include(AddLLVM)
|
||||
|
||||
if (NOT DEFINED LIBCXX_TEST_DEPS)
|
||||
message(FATAL_ERROR "Expected LIBCXX_TEST_DEPS to be defined")
|
||||
endif()
|
||||
|
||||
configure_lit_site_cfg(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py)
|
||||
|
||||
set(BENCHMARK_LIT_ARGS "--show-all --show-xfail --show-unsupported ${LIT_ARGS_DEFAULT}")
|
||||
|
||||
add_lit_target(check-cxx-benchmarks
|
||||
"Running libcxx benchmarks tests"
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS cxx-benchmarks ${LIBCXX_TEST_DEPS}
|
||||
ARGS ${BENCHMARK_LIT_ARGS})
|
||||
endif()
|
@ -1,133 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class D, class E, size_t I>
|
||||
struct EnumValue : std::integral_constant<E, static_cast<E>(I)> {
|
||||
static std::string name() { return std::string("_") + D::Names[I]; }
|
||||
};
|
||||
|
||||
template <class D, class E, size_t ...Idxs>
|
||||
constexpr auto makeEnumValueTuple(std::index_sequence<Idxs...>) {
|
||||
return std::make_tuple(EnumValue<D, E, Idxs>{}...);
|
||||
}
|
||||
|
||||
template <class B>
|
||||
static auto skip(const B& Bench, int) -> decltype(Bench.skip()) {
|
||||
return Bench.skip();
|
||||
}
|
||||
template <class B>
|
||||
static auto skip(const B& Bench, char) {
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class B, class Args, size_t... Is>
|
||||
void makeBenchmarkFromValuesImpl(const Args& A, std::index_sequence<Is...>) {
|
||||
for (auto& V : A) {
|
||||
B Bench{std::get<Is>(V)...};
|
||||
if (!internal::skip(Bench, 0)) {
|
||||
benchmark::RegisterBenchmark(Bench.name().c_str(),
|
||||
[=](benchmark::State& S) { Bench.run(S); });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <class B, class... Args>
|
||||
void makeBenchmarkFromValues(const std::vector<std::tuple<Args...> >& A) {
|
||||
makeBenchmarkFromValuesImpl<B>(A, std::index_sequence_for<Args...>());
|
||||
}
|
||||
|
||||
template <template <class...> class B, class Args, class... U>
|
||||
void makeBenchmarkImpl(const Args& A, std::tuple<U...> t) {
|
||||
makeBenchmarkFromValues<B<U...> >(A);
|
||||
}
|
||||
|
||||
template <template <class...> class B, class Args, class... U,
|
||||
class... T, class... Tuples>
|
||||
void makeBenchmarkImpl(const Args& A, std::tuple<U...>, std::tuple<T...>,
|
||||
Tuples... rest) {
|
||||
(internal::makeBenchmarkImpl<B>(A, std::tuple<U..., T>(), rest...), ...);
|
||||
}
|
||||
|
||||
template <class R, class T>
|
||||
void allValueCombinations(R& Result, const T& Final) {
|
||||
return Result.push_back(Final);
|
||||
}
|
||||
|
||||
template <class R, class T, class V, class... Vs>
|
||||
void allValueCombinations(R& Result, const T& Prev, const V& Value,
|
||||
const Vs&... Values) {
|
||||
for (const auto& E : Value) {
|
||||
allValueCombinations(Result, std::tuple_cat(Prev, std::make_tuple(E)),
|
||||
Values...);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
// CRTP class that enables using enum types as a dimension for
|
||||
// makeCartesianProductBenchmark below.
|
||||
// The type passed to `B` will be a std::integral_constant<E, e>, with the
|
||||
// additional static function `name()` that returns the stringified name of the
|
||||
// label.
|
||||
//
|
||||
// Eg:
|
||||
// enum class MyEnum { A, B };
|
||||
// struct AllMyEnum : EnumValuesAsTuple<AllMyEnum, MyEnum, 2> {
|
||||
// static constexpr absl::string_view Names[] = {"A", "B"};
|
||||
// };
|
||||
template <class Derived, class EnumType, size_t NumLabels>
|
||||
using EnumValuesAsTuple =
|
||||
decltype(internal::makeEnumValueTuple<Derived, EnumType>(
|
||||
std::make_index_sequence<NumLabels>{}));
|
||||
|
||||
// Instantiates B<T0, T1, ..., TN> where <Ti...> are the combinations in the
|
||||
// cartesian product of `Tuples...`, and pass (arg0, ..., argN) as constructor
|
||||
// arguments where `(argi...)` are the combination in the cartesian product of
|
||||
// the runtime values of `A...`.
|
||||
// B<T...> requires:
|
||||
// - std::string name(args...): The name of the benchmark.
|
||||
// - void run(benchmark::State&, args...): The body of the benchmark.
|
||||
// It can also optionally provide:
|
||||
// - bool skip(args...): When `true`, skips the combination. Default is false.
|
||||
//
|
||||
// Returns int to facilitate registration. The return value is unspecified.
|
||||
template <template <class...> class B, class... Tuples, class... Args>
|
||||
int makeCartesianProductBenchmark(const Args&... A) {
|
||||
std::vector<std::tuple<typename Args::value_type...> > V;
|
||||
internal::allValueCombinations(V, std::tuple<>(), A...);
|
||||
internal::makeBenchmarkImpl<B>(V, std::tuple<>(), Tuples()...);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <class B, class... Args>
|
||||
int makeCartesianProductBenchmark(const Args&... A) {
|
||||
std::vector<std::tuple<typename Args::value_type...> > V;
|
||||
internal::allValueCombinations(V, std::tuple<>(), A...);
|
||||
internal::makeBenchmarkFromValues<B>(V);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// When `opaque` is true, this function hides the runtime state of `value` from
|
||||
// the optimizer.
|
||||
// It returns `value`.
|
||||
template <class T>
|
||||
TEST_ALWAYS_INLINE inline T maybeOpaque(T value, bool opaque) {
|
||||
if (opaque) benchmark::DoNotOptimize(value);
|
||||
return value;
|
||||
}
|
@ -1,154 +0,0 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef BENCHMARK_CONTAINER_BENCHMARKS_H
|
||||
#define BENCHMARK_CONTAINER_BENCHMARKS_H
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "Utilities.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace ContainerBenchmarks {
|
||||
|
||||
template <class Container>
|
||||
void BM_ConstructSize(benchmark::State& st, Container) {
|
||||
auto size = st.range(0);
|
||||
for (auto _ : st) {
|
||||
Container c(size);
|
||||
DoNotOptimizeData(c);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
void BM_ConstructSizeValue(benchmark::State& st, Container, typename Container::value_type const& val) {
|
||||
const auto size = st.range(0);
|
||||
for (auto _ : st) {
|
||||
Container c(size, val);
|
||||
DoNotOptimizeData(c);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
void BM_ConstructIterIter(benchmark::State& st, Container, GenInputs gen) {
|
||||
auto in = gen(st.range(0));
|
||||
const auto begin = in.begin();
|
||||
const auto end = in.end();
|
||||
benchmark::DoNotOptimize(&in);
|
||||
while (st.KeepRunning()) {
|
||||
Container c(begin, end);
|
||||
DoNotOptimizeData(c);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
void BM_InsertValue(benchmark::State& st, Container c, GenInputs gen) {
|
||||
auto in = gen(st.range(0));
|
||||
const auto end = in.end();
|
||||
while (st.KeepRunning()) {
|
||||
c.clear();
|
||||
for (auto it = in.begin(); it != end; ++it) {
|
||||
benchmark::DoNotOptimize(&(*c.insert(*it).first));
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
void BM_InsertValueRehash(benchmark::State& st, Container c, GenInputs gen) {
|
||||
auto in = gen(st.range(0));
|
||||
const auto end = in.end();
|
||||
while (st.KeepRunning()) {
|
||||
c.clear();
|
||||
c.rehash(16);
|
||||
for (auto it = in.begin(); it != end; ++it) {
|
||||
benchmark::DoNotOptimize(&(*c.insert(*it).first));
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
void BM_InsertDuplicate(benchmark::State& st, Container c, GenInputs gen) {
|
||||
auto in = gen(st.range(0));
|
||||
const auto end = in.end();
|
||||
c.insert(in.begin(), in.end());
|
||||
benchmark::DoNotOptimize(&c);
|
||||
benchmark::DoNotOptimize(&in);
|
||||
while (st.KeepRunning()) {
|
||||
for (auto it = in.begin(); it != end; ++it) {
|
||||
benchmark::DoNotOptimize(&(*c.insert(*it).first));
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
void BM_EmplaceDuplicate(benchmark::State& st, Container c, GenInputs gen) {
|
||||
auto in = gen(st.range(0));
|
||||
const auto end = in.end();
|
||||
c.insert(in.begin(), in.end());
|
||||
benchmark::DoNotOptimize(&c);
|
||||
benchmark::DoNotOptimize(&in);
|
||||
while (st.KeepRunning()) {
|
||||
for (auto it = in.begin(); it != end; ++it) {
|
||||
benchmark::DoNotOptimize(&(*c.emplace(*it).first));
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
static void BM_Find(benchmark::State& st, Container c, GenInputs gen) {
|
||||
auto in = gen(st.range(0));
|
||||
c.insert(in.begin(), in.end());
|
||||
benchmark::DoNotOptimize(&(*c.begin()));
|
||||
const auto end = in.data() + in.size();
|
||||
while (st.KeepRunning()) {
|
||||
for (auto it = in.data(); it != end; ++it) {
|
||||
benchmark::DoNotOptimize(&(*c.find(*it)));
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
static void BM_FindRehash(benchmark::State& st, Container c, GenInputs gen) {
|
||||
c.rehash(8);
|
||||
auto in = gen(st.range(0));
|
||||
c.insert(in.begin(), in.end());
|
||||
benchmark::DoNotOptimize(&(*c.begin()));
|
||||
const auto end = in.data() + in.size();
|
||||
while (st.KeepRunning()) {
|
||||
for (auto it = in.data(); it != end; ++it) {
|
||||
benchmark::DoNotOptimize(&(*c.find(*it)));
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Container, class GenInputs>
|
||||
static void BM_Rehash(benchmark::State& st, Container c, GenInputs gen) {
|
||||
auto in = gen(st.range(0));
|
||||
c.max_load_factor(3.0);
|
||||
c.insert(in.begin(), in.end());
|
||||
benchmark::DoNotOptimize(c);
|
||||
const auto bucket_count = c.bucket_count();
|
||||
while (st.KeepRunning()) {
|
||||
c.rehash(bucket_count + 1);
|
||||
c.rehash(bucket_count);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace ContainerBenchmarks
|
||||
|
||||
#endif // BENCHMARK_CONTAINER_BENCHMARKS_H
|
@ -1,143 +0,0 @@
|
||||
#ifndef BENCHMARK_GENERATE_INPUT_H
|
||||
#define BENCHMARK_GENERATE_INPUT_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
|
||||
static const char Letters[] = {
|
||||
'0','1','2','3','4',
|
||||
'5','6','7','8','9',
|
||||
'A','B','C','D','E','F',
|
||||
'G','H','I','J','K',
|
||||
'L','M','N','O','P',
|
||||
'Q','R','S','T','U',
|
||||
'V','W','X','Y','Z',
|
||||
'a','b','c','d','e','f',
|
||||
'g','h','i','j','k',
|
||||
'l','m','n','o','p',
|
||||
'q','r','s','t','u',
|
||||
'v','w','x','y','z'
|
||||
};
|
||||
static const std::size_t LettersSize = sizeof(Letters);
|
||||
|
||||
inline std::default_random_engine& getRandomEngine() {
|
||||
static std::default_random_engine RandEngine(std::random_device{}());
|
||||
return RandEngine;
|
||||
}
|
||||
|
||||
|
||||
inline char getRandomChar() {
|
||||
std::uniform_int_distribution<> LettersDist(0, LettersSize-1);
|
||||
return Letters[LettersDist(getRandomEngine())];
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
inline IntT getRandomInteger(IntT Min, IntT Max) {
|
||||
std::uniform_int_distribution<unsigned long long> dist(Min, Max);
|
||||
return static_cast<IntT>(dist(getRandomEngine()));
|
||||
}
|
||||
|
||||
inline std::string getRandomString(std::size_t Len) {
|
||||
std::string str(Len, 0);
|
||||
std::generate_n(str.begin(), Len, &getRandomChar);
|
||||
return str;
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
inline std::vector<IntT> getDuplicateIntegerInputs(size_t N) {
|
||||
std::vector<IntT> inputs(N, static_cast<IntT>(-1));
|
||||
return inputs;
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
inline std::vector<IntT> getSortedIntegerInputs(size_t N) {
|
||||
std::vector<IntT> inputs;
|
||||
for (size_t i=0; i < N; i += 1)
|
||||
inputs.push_back(i);
|
||||
return inputs;
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
std::vector<IntT> getSortedLargeIntegerInputs(size_t N) {
|
||||
std::vector<IntT> inputs;
|
||||
for (size_t i=0; i < N; ++i) {
|
||||
inputs.push_back(i + N);
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
std::vector<IntT> getSortedTopBitsIntegerInputs(size_t N) {
|
||||
std::vector<IntT> inputs = getSortedIntegerInputs<IntT>(N);
|
||||
for (auto& E : inputs) E <<= ((sizeof(IntT) / 2) * CHAR_BIT);
|
||||
return inputs;
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
inline std::vector<IntT> getReverseSortedIntegerInputs(size_t N) {
|
||||
std::vector<IntT> inputs;
|
||||
std::size_t i = N;
|
||||
while (i > 0) {
|
||||
--i;
|
||||
inputs.push_back(i);
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
std::vector<IntT> getPipeOrganIntegerInputs(size_t N) {
|
||||
std::vector<IntT> v; v.reserve(N);
|
||||
for (size_t i = 0; i < N/2; ++i) v.push_back(i);
|
||||
for (size_t i = N/2; i < N; ++i) v.push_back(N - i);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
template <class IntT>
|
||||
std::vector<IntT> getRandomIntegerInputs(size_t N) {
|
||||
std::vector<IntT> inputs;
|
||||
for (size_t i=0; i < N; ++i) {
|
||||
inputs.push_back(getRandomInteger<IntT>(0, std::numeric_limits<IntT>::max()));
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> getDuplicateStringInputs(size_t N) {
|
||||
std::vector<std::string> inputs(N, getRandomString(1024));
|
||||
return inputs;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> getRandomStringInputs(size_t N) {
|
||||
std::vector<std::string> inputs;
|
||||
for (size_t i=0; i < N; ++i) {
|
||||
inputs.push_back(getRandomString(1024));
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> getSortedStringInputs(size_t N) {
|
||||
std::vector<std::string> inputs = getRandomStringInputs(N);
|
||||
std::sort(inputs.begin(), inputs.end());
|
||||
return inputs;
|
||||
}
|
||||
|
||||
inline std::vector<std::string> getReverseSortedStringInputs(size_t N) {
|
||||
std::vector<std::string> inputs = getSortedStringInputs(N);
|
||||
std::reverse(inputs.begin(), inputs.end());
|
||||
return inputs;
|
||||
}
|
||||
|
||||
inline std::vector<const char*> getRandomCStringInputs(size_t N) {
|
||||
static std::vector<std::string> inputs = getRandomStringInputs(N);
|
||||
std::vector<const char*> cinputs;
|
||||
for (auto const& str : inputs)
|
||||
cinputs.push_back(str.c_str());
|
||||
return cinputs;
|
||||
}
|
||||
|
||||
|
||||
#endif // BENCHMARK_GENERATE_INPUT_H
|
@ -1,33 +0,0 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef BENCHMARK_UTILITIES_H
|
||||
#define BENCHMARK_UTILITIES_H
|
||||
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace UtilitiesInternal {
|
||||
template <class Container>
|
||||
auto HaveDataImpl(int) -> decltype((std::declval<Container&>().data(), std::true_type{}));
|
||||
template <class Container>
|
||||
auto HaveDataImpl(long) -> std::false_type;
|
||||
template <class T>
|
||||
using HasData = decltype(HaveDataImpl<T>(0));
|
||||
} // namespace UtilitiesInternal
|
||||
|
||||
template <class Container, std::enable_if_t<UtilitiesInternal::HasData<Container>::value>* = nullptr>
|
||||
void DoNotOptimizeData(Container &c) { benchmark::DoNotOptimize(c.data()); }
|
||||
template <class Container, std::enable_if_t<!UtilitiesInternal::HasData<Container>::value>* = nullptr>
|
||||
void DoNotOptimizeData(Container &c) { benchmark::DoNotOptimize(&c); }
|
||||
|
||||
|
||||
#endif // BENCHMARK_UTILITIES_H
|
@ -1,58 +0,0 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef BENCHMARK_VARIANT_BENCHMARKS_H
|
||||
#define BENCHMARK_VARIANT_BENCHMARKS_H
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "GenerateInput.h"
|
||||
|
||||
namespace VariantBenchmarks {
|
||||
|
||||
template <std::size_t I>
|
||||
struct S {
|
||||
static constexpr size_t v = I;
|
||||
};
|
||||
|
||||
template <std::size_t N, std::size_t... Is>
|
||||
static auto genVariants(std::index_sequence<Is...>) {
|
||||
using V = std::variant<S<Is>...>;
|
||||
using F = V (*)();
|
||||
static constexpr F fs[] = {[] { return V(std::in_place_index<Is>); }...};
|
||||
|
||||
std::array<V, N> result = {};
|
||||
for (auto& v : result) {
|
||||
v = fs[getRandomInteger(0ul, sizeof...(Is) - 1)]();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <std::size_t N, std::size_t Alts>
|
||||
static void BM_Visit(benchmark::State& state) {
|
||||
auto args = genVariants<N>(std::make_index_sequence<Alts>{});
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(std::apply(
|
||||
[](auto... vs) {
|
||||
return std::visit([](auto... is) { return (is.v + ... + 0); }, vs...);
|
||||
},
|
||||
args));
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace VariantBenchmarks
|
||||
|
||||
#endif // BENCHMARK_VARIANT_BENCHMARKS_H
|
@ -1,124 +0,0 @@
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename I, typename N>
|
||||
std::array<I, 10> every_10th_percentile_N(I first, N n) {
|
||||
N step = n / 10;
|
||||
std::array<I, 10> res;
|
||||
|
||||
for (size_t i = 0; i < 10; ++i) {
|
||||
res[i] = first;
|
||||
std::advance(first, step);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
template <class IntT>
|
||||
struct TestIntBase {
|
||||
static std::vector<IntT> generateInput(size_t size) {
|
||||
std::vector<IntT> Res(size);
|
||||
std::generate(Res.begin(), Res.end(),
|
||||
[] { return getRandomInteger<IntT>(0, std::numeric_limits<IntT>::max()); });
|
||||
return Res;
|
||||
}
|
||||
};
|
||||
|
||||
struct TestInt32 : TestIntBase<std::int32_t> {
|
||||
static constexpr const char* Name = "TestInt32";
|
||||
};
|
||||
|
||||
struct TestInt64 : TestIntBase<std::int64_t> {
|
||||
static constexpr const char* Name = "TestInt64";
|
||||
};
|
||||
|
||||
struct TestUint32 : TestIntBase<std::uint32_t> {
|
||||
static constexpr const char* Name = "TestUint32";
|
||||
};
|
||||
|
||||
struct TestMediumString {
|
||||
static constexpr const char* Name = "TestMediumString";
|
||||
static constexpr size_t StringSize = 32;
|
||||
|
||||
static std::vector<std::string> generateInput(size_t size) {
|
||||
std::vector<std::string> Res(size);
|
||||
std::generate(Res.begin(), Res.end(), [] { return getRandomString(StringSize); });
|
||||
return Res;
|
||||
}
|
||||
};
|
||||
|
||||
using AllTestTypes = std::tuple<TestInt32, TestInt64, TestUint32, TestMediumString>;
|
||||
|
||||
struct LowerBoundAlg {
|
||||
template <class I, class V>
|
||||
I operator()(I first, I last, const V& value) const {
|
||||
return std::lower_bound(first, last, value);
|
||||
}
|
||||
|
||||
static constexpr const char* Name = "LowerBoundAlg";
|
||||
};
|
||||
|
||||
struct UpperBoundAlg {
|
||||
template <class I, class V>
|
||||
I operator()(I first, I last, const V& value) const {
|
||||
return std::upper_bound(first, last, value);
|
||||
}
|
||||
|
||||
static constexpr const char* Name = "UpperBoundAlg";
|
||||
};
|
||||
|
||||
struct EqualRangeAlg {
|
||||
template <class I, class V>
|
||||
std::pair<I, I> operator()(I first, I last, const V& value) const {
|
||||
return std::equal_range(first, last, value);
|
||||
}
|
||||
|
||||
static constexpr const char* Name = "EqualRangeAlg";
|
||||
};
|
||||
|
||||
using AllAlgs = std::tuple<LowerBoundAlg, UpperBoundAlg, EqualRangeAlg>;
|
||||
|
||||
template <class Alg, class TestType>
|
||||
struct PartitionPointBench {
|
||||
size_t Quantity;
|
||||
|
||||
std::string name() const {
|
||||
return std::string("PartitionPointBench_") + Alg::Name + "_" +
|
||||
TestType::Name + '/' + std::to_string(Quantity);
|
||||
}
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
auto Data = TestType::generateInput(Quantity);
|
||||
std::sort(Data.begin(), Data.end());
|
||||
auto Every10Percentile = every_10th_percentile_N(Data.begin(), Data.size());
|
||||
|
||||
for (auto _ : state) {
|
||||
for (auto Test : Every10Percentile)
|
||||
benchmark::DoNotOptimize(Alg{}(Data.begin(), Data.end(), *Test));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
const std::vector<size_t> Quantities = {1 << 8, 1 << 10, 1 << 20};
|
||||
makeCartesianProductBenchmark<PartitionPointBench, AllAlgs, AllTestTypes>(
|
||||
Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,244 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LIBCXX_ALGORITHMS_COMMON_H
|
||||
#define LIBCXX_ALGORITHMS_COMMON_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "../CartesianBenchmarks.h"
|
||||
#include "../GenerateInput.h"
|
||||
|
||||
enum class ValueType { Uint32, Uint64, Pair, Tuple, String, Float };
|
||||
struct AllValueTypes : EnumValuesAsTuple<AllValueTypes, ValueType, 6> {
|
||||
static constexpr const char* Names[] = {"uint32", "uint64", "pair<uint32, uint32>", "tuple<uint32, uint64, uint32>",
|
||||
"string", "float"};
|
||||
};
|
||||
|
||||
using Types = std::tuple< uint32_t, uint64_t, std::pair<uint32_t, uint32_t>, std::tuple<uint32_t, uint64_t, uint32_t>,
|
||||
std::string, float >;
|
||||
|
||||
template <class V>
|
||||
using Value = std::tuple_element_t<(int)V::value, Types>;
|
||||
|
||||
enum class Order {
|
||||
Random,
|
||||
Ascending,
|
||||
Descending,
|
||||
SingleElement,
|
||||
PipeOrgan,
|
||||
Heap,
|
||||
QuickSortAdversary,
|
||||
};
|
||||
struct AllOrders : EnumValuesAsTuple<AllOrders, Order, 7> {
|
||||
static constexpr const char* Names[] = {"Random", "Ascending",
|
||||
"Descending", "SingleElement",
|
||||
"PipeOrgan", "Heap",
|
||||
"QuickSortAdversary"};
|
||||
};
|
||||
|
||||
// fillAdversarialQuickSortInput fills the input vector with N int-like values.
|
||||
// These values are arranged in such a way that they would invoke O(N^2)
|
||||
// behavior on any quick sort implementation that satisifies certain conditions.
|
||||
// Details are available in the following paper:
|
||||
// "A Killer Adversary for Quicksort", M. D. McIlroy, Software-Practice &
|
||||
// Experience Volume 29 Issue 4 April 10, 1999 pp 341-344.
|
||||
// https://dl.acm.org/doi/10.5555/311868.311871.
|
||||
template <class T>
|
||||
void fillAdversarialQuickSortInput(T& V, size_t N) {
|
||||
assert(N > 0);
|
||||
// If an element is equal to gas, it indicates that the value of the element
|
||||
// is still to be decided and may change over the course of time.
|
||||
const unsigned int gas = N - 1;
|
||||
V.resize(N);
|
||||
for (unsigned int i = 0; i < N; ++i) {
|
||||
V[i] = gas;
|
||||
}
|
||||
// Candidate for the pivot position.
|
||||
int candidate = 0;
|
||||
int nsolid = 0;
|
||||
// Populate all positions in the generated input to gas.
|
||||
std::vector<int> ascVals(V.size());
|
||||
// Fill up with ascending values from 0 to V.size()-1. These will act as
|
||||
// indices into V.
|
||||
std::iota(ascVals.begin(), ascVals.end(), 0);
|
||||
std::sort(ascVals.begin(), ascVals.end(), [&](int x, int y) {
|
||||
if (V[x] == gas && V[y] == gas) {
|
||||
// We are comparing two inputs whose value is still to be decided.
|
||||
if (x == candidate) {
|
||||
V[x] = nsolid++;
|
||||
} else {
|
||||
V[y] = nsolid++;
|
||||
}
|
||||
}
|
||||
if (V[x] == gas) {
|
||||
candidate = x;
|
||||
} else if (V[y] == gas) {
|
||||
candidate = y;
|
||||
}
|
||||
return V[x] < V[y];
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void fillValues(std::vector<T>& V, size_t N, Order O) {
|
||||
if (O == Order::SingleElement) {
|
||||
V.resize(N, 0);
|
||||
} else if (O == Order::QuickSortAdversary) {
|
||||
fillAdversarialQuickSortInput(V, N);
|
||||
} else {
|
||||
while (V.size() < N)
|
||||
V.push_back(V.size());
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void fillValues(std::vector<std::pair<T, T> >& V, size_t N, Order O) {
|
||||
if (O == Order::SingleElement) {
|
||||
V.resize(N, std::make_pair(0, 0));
|
||||
} else {
|
||||
while (V.size() < N)
|
||||
// Half of array will have the same first element.
|
||||
if (V.size() % 2) {
|
||||
V.push_back(std::make_pair(V.size(), V.size()));
|
||||
} else {
|
||||
V.push_back(std::make_pair(0, V.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
void fillValues(std::vector<std::tuple<T1, T2, T3> >& V, size_t N, Order O) {
|
||||
if (O == Order::SingleElement) {
|
||||
V.resize(N, std::make_tuple(0, 0, 0));
|
||||
} else {
|
||||
while (V.size() < N)
|
||||
// One third of array will have the same first element.
|
||||
// One third of array will have the same first element and the same second element.
|
||||
switch (V.size() % 3) {
|
||||
case 0:
|
||||
V.push_back(std::make_tuple(V.size(), V.size(), V.size()));
|
||||
break;
|
||||
case 1:
|
||||
V.push_back(std::make_tuple(0, V.size(), V.size()));
|
||||
break;
|
||||
case 2:
|
||||
V.push_back(std::make_tuple(0, 0, V.size()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void fillValues(std::vector<std::string>& V, size_t N, Order O) {
|
||||
if (O == Order::SingleElement) {
|
||||
V.resize(N, getRandomString(64));
|
||||
} else {
|
||||
while (V.size() < N)
|
||||
V.push_back(getRandomString(64));
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void sortValues(T& V, Order O) {
|
||||
switch (O) {
|
||||
case Order::Random: {
|
||||
std::random_device R;
|
||||
std::mt19937 M(R());
|
||||
std::shuffle(V.begin(), V.end(), M);
|
||||
break;
|
||||
}
|
||||
case Order::Ascending:
|
||||
std::sort(V.begin(), V.end());
|
||||
break;
|
||||
case Order::Descending:
|
||||
std::sort(V.begin(), V.end(), std::greater<>());
|
||||
break;
|
||||
case Order::SingleElement:
|
||||
// Nothing to do
|
||||
break;
|
||||
case Order::PipeOrgan:
|
||||
std::sort(V.begin(), V.end());
|
||||
std::reverse(V.begin() + V.size() / 2, V.end());
|
||||
break;
|
||||
case Order::Heap:
|
||||
std::make_heap(V.begin(), V.end());
|
||||
break;
|
||||
case Order::QuickSortAdversary:
|
||||
// Nothing to do
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr size_t TestSetElements =
|
||||
#if !TEST_HAS_FEATURE(memory_sanitizer)
|
||||
1 << 18;
|
||||
#else
|
||||
1 << 14;
|
||||
#endif
|
||||
|
||||
template <class ValueType>
|
||||
std::vector<std::vector<Value<ValueType> > > makeOrderedValues(size_t N,
|
||||
Order O) {
|
||||
std::vector<std::vector<Value<ValueType> > > Ret;
|
||||
const size_t NumCopies = std::max(size_t{1}, TestSetElements / N);
|
||||
Ret.resize(NumCopies);
|
||||
for (auto& V : Ret) {
|
||||
fillValues(V, N, O);
|
||||
sortValues(V, O);
|
||||
}
|
||||
return Ret;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
TEST_ALWAYS_INLINE void resetCopies(benchmark::State& state, T& Copies,
|
||||
U& Orig) {
|
||||
state.PauseTiming();
|
||||
for (auto& Copy : Copies)
|
||||
Copy = Orig;
|
||||
state.ResumeTiming();
|
||||
}
|
||||
|
||||
enum class BatchSize {
|
||||
CountElements,
|
||||
CountBatch,
|
||||
};
|
||||
|
||||
template <class ValueType, class F>
|
||||
void runOpOnCopies(benchmark::State& state, size_t Quantity, Order O,
|
||||
BatchSize Count, F Body) {
|
||||
auto Copies = makeOrderedValues<ValueType>(Quantity, O);
|
||||
auto Orig = Copies;
|
||||
|
||||
const size_t Batch = Count == BatchSize::CountElements
|
||||
? Copies.size() * Quantity
|
||||
: Copies.size();
|
||||
while (state.KeepRunningBatch(Batch)) {
|
||||
for (auto& Copy : Copies) {
|
||||
Body(Copy);
|
||||
benchmark::DoNotOptimize(Copy);
|
||||
}
|
||||
state.PauseTiming();
|
||||
Copies = Orig;
|
||||
state.ResumeTiming();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::vector<size_t> Quantities = {1 << 0, 1 << 2, 1 << 4, 1 << 6,
|
||||
1 << 8, 1 << 10, 1 << 14,
|
||||
// Running each benchmark in parallel consumes too much memory with MSAN
|
||||
// and can lead to the test process being killed.
|
||||
#if !TEST_HAS_FEATURE(memory_sanitizer)
|
||||
1 << 18
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // LIBCXX_ALGORITHMS_COMMON_H
|
@ -1,42 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType>
|
||||
struct LowerBound {
|
||||
size_t Quantity;
|
||||
|
||||
mutable std::mt19937_64 rng { std::random_device{}() };
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order::Ascending, BatchSize::CountBatch, [&](auto& Copy) {
|
||||
auto result = std::lower_bound(Copy.begin(), Copy.end(), Copy[rng() % Copy.size()]);
|
||||
benchmark::DoNotOptimize(result);
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_LowerBound" + ValueType::name() + "_" + std::to_string(Quantity);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<LowerBound, AllValueTypes>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct MakeHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements,
|
||||
[](auto& Copy) { std::make_heap(Copy.begin(), Copy.end()); });
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_MakeHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<MakeHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct MakeThenSortHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), BatchSize::CountElements,
|
||||
[](auto& Copy) {
|
||||
std::make_heap(Copy.begin(), Copy.end());
|
||||
std::sort_heap(Copy.begin(), Copy.end());
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_MakeThenSortHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<MakeThenSortHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct MinMaxElement {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), BatchSize::CountElements, [](auto& Copy) {
|
||||
benchmark::DoNotOptimize(std::minmax_element(Copy.begin(), Copy.end()));
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_MinMaxElement" + ValueType::name() + Order::name() + "_" + std::to_string(Quantity);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<MinMaxElement, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType>
|
||||
struct PopHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements, [](auto& Copy) {
|
||||
for (auto B = Copy.begin(), I = Copy.end(); I != B; --I) {
|
||||
std::pop_heap(B, I);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_PopHeap" + ValueType::name() + "_" + std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<PopHeap, AllValueTypes>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct PushHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements, [](auto& Copy) {
|
||||
for (auto I = Copy.begin(), E = Copy.end(); I != E; ++I) {
|
||||
std::push_heap(Copy.begin(), I + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_PushHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<PushHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct RangesMakeHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements,
|
||||
[](auto& Copy) { std::ranges::make_heap(Copy); });
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_RangesMakeHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<RangesMakeHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct RangesMakeThenSortHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(state, Quantity, Order(), BatchSize::CountElements,
|
||||
[](auto& Copy) {
|
||||
std::ranges::make_heap(Copy);
|
||||
std::ranges::sort_heap(Copy);
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_RangesMakeThenSortHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<RangesMakeThenSortHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType>
|
||||
struct RangesPopHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements, [](auto& Copy) {
|
||||
for (auto B = Copy.begin(), I = Copy.end(); I != B; --I) {
|
||||
std::ranges::pop_heap(B, I);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_RangesPopHeap" + ValueType::name() + "_" + std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<RangesPopHeap, AllValueTypes>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct RangesPushHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements, [](auto& Copy) {
|
||||
for (auto I = Copy.begin(), E = Copy.end(); I != E; ++I) {
|
||||
std::ranges::push_heap(Copy.begin(), I + 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_RangesPushHeap" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<RangesPushHeap, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct Sort {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements,
|
||||
[](auto& Copy) { std::ranges::sort(Copy); });
|
||||
}
|
||||
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_RangesSort" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<Sort, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType>
|
||||
struct RangesSortHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order::Heap, BatchSize::CountElements,
|
||||
[](auto& Copy) { std::ranges::sort_heap(Copy); });
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_RangesSortHeap" + ValueType::name() + "_" + std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<RangesSortHeap, AllValueTypes>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct StableSort {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements,
|
||||
[](auto& Copy) { std::ranges::stable_sort(Copy); });
|
||||
}
|
||||
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_RangesStableSort" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<StableSort, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct Sort {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements,
|
||||
[](auto& Copy) { std::sort(Copy.begin(), Copy.end()); });
|
||||
}
|
||||
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_Sort" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<Sort, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType>
|
||||
struct SortHeap {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order::Heap, BatchSize::CountElements,
|
||||
[](auto& Copy) { std::sort_heap(Copy.begin(), Copy.end()); });
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_SortHeap" + ValueType::name() + "_" + std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<SortHeap, AllValueTypes>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace {
|
||||
template <class ValueType, class Order>
|
||||
struct StableSort {
|
||||
size_t Quantity;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
runOpOnCopies<ValueType>(
|
||||
state, Quantity, Order(), BatchSize::CountElements,
|
||||
[](auto& Copy) { std::stable_sort(Copy.begin(), Copy.end()); });
|
||||
}
|
||||
|
||||
bool skip() const { return Order() == ::Order::Heap; }
|
||||
|
||||
std::string name() const {
|
||||
return "BM_StableSort" + ValueType::name() + Order::name() + "_" +
|
||||
std::to_string(Quantity);
|
||||
};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
makeCartesianProductBenchmark<StableSort, AllValueTypes, AllOrders>(Quantities);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,135 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include <new>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
struct PointerList {
|
||||
PointerList* Next = nullptr;
|
||||
};
|
||||
|
||||
struct MallocWrapper {
|
||||
__attribute__((always_inline))
|
||||
static void* Allocate(size_t N) {
|
||||
return std::malloc(N);
|
||||
}
|
||||
__attribute__((always_inline))
|
||||
static void Deallocate(void* P, size_t) {
|
||||
std::free(P);
|
||||
}
|
||||
};
|
||||
|
||||
struct NewWrapper {
|
||||
__attribute__((always_inline))
|
||||
static void* Allocate(size_t N) {
|
||||
return ::operator new(N);
|
||||
}
|
||||
__attribute__((always_inline))
|
||||
static void Deallocate(void* P, size_t) {
|
||||
::operator delete(P);
|
||||
}
|
||||
};
|
||||
|
||||
struct BuiltinNewWrapper {
|
||||
__attribute__((always_inline))
|
||||
static void* Allocate(size_t N) {
|
||||
return __builtin_operator_new(N);
|
||||
}
|
||||
__attribute__((always_inline))
|
||||
static void Deallocate(void* P, size_t) {
|
||||
__builtin_operator_delete(P);
|
||||
}
|
||||
};
|
||||
|
||||
struct BuiltinSizedNewWrapper {
|
||||
__attribute__((always_inline))
|
||||
static void* Allocate(size_t N) {
|
||||
return __builtin_operator_new(N);
|
||||
}
|
||||
__attribute__((always_inline))
|
||||
static void Deallocate(void* P, size_t N) {
|
||||
__builtin_operator_delete(P, N);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <class AllocWrapper>
|
||||
static void BM_AllocateAndDeallocate(benchmark::State& st) {
|
||||
const size_t alloc_size = st.range(0);
|
||||
while (st.KeepRunning()) {
|
||||
void* p = AllocWrapper::Allocate(alloc_size);
|
||||
benchmark::DoNotOptimize(p);
|
||||
AllocWrapper::Deallocate(p, alloc_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class AllocWrapper>
|
||||
static void BM_AllocateOnly(benchmark::State& st) {
|
||||
const size_t alloc_size = st.range(0);
|
||||
PointerList *Start = nullptr;
|
||||
|
||||
while (st.KeepRunning()) {
|
||||
PointerList* p = (PointerList*)AllocWrapper::Allocate(alloc_size);
|
||||
benchmark::DoNotOptimize(p);
|
||||
p->Next = Start;
|
||||
Start = p;
|
||||
}
|
||||
|
||||
PointerList *Next = Start;
|
||||
while (Next) {
|
||||
PointerList *Tmp = Next;
|
||||
Next = Tmp->Next;
|
||||
AllocWrapper::Deallocate(Tmp, alloc_size);
|
||||
}
|
||||
}
|
||||
|
||||
template <class AllocWrapper>
|
||||
static void BM_DeallocateOnly(benchmark::State& st) {
|
||||
const size_t alloc_size = st.range(0);
|
||||
const auto NumAllocs = st.max_iterations;
|
||||
|
||||
std::vector<void*> Pointers(NumAllocs);
|
||||
for (auto& p : Pointers) {
|
||||
p = AllocWrapper::Allocate(alloc_size);
|
||||
}
|
||||
|
||||
void** Data = Pointers.data();
|
||||
void** const End = Pointers.data() + Pointers.size();
|
||||
while (st.KeepRunning()) {
|
||||
AllocWrapper::Deallocate(*Data, alloc_size);
|
||||
Data += 1;
|
||||
}
|
||||
assert(Data == End);
|
||||
}
|
||||
|
||||
static int RegisterAllocBenchmarks() {
|
||||
using FnType = void(*)(benchmark::State&);
|
||||
struct {
|
||||
const char* name;
|
||||
FnType func;
|
||||
} TestCases[] = {
|
||||
{"BM_Malloc", &BM_AllocateAndDeallocate<MallocWrapper>},
|
||||
{"BM_New", &BM_AllocateAndDeallocate<NewWrapper>},
|
||||
{"BM_BuiltinNewDelete", BM_AllocateAndDeallocate<BuiltinNewWrapper>},
|
||||
{"BM_BuiltinSizedNewDelete", BM_AllocateAndDeallocate<BuiltinSizedNewWrapper>},
|
||||
{"BM_BuiltinNewAllocateOnly", BM_AllocateOnly<BuiltinSizedNewWrapper>},
|
||||
{"BM_BuiltinNewSizedDeallocateOnly", BM_DeallocateOnly<BuiltinSizedNewWrapper>},
|
||||
|
||||
};
|
||||
for (auto TC : TestCases) {
|
||||
benchmark::RegisterBenchmark(TC.name, TC.func)->Range(16, 4096 * 2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int Sink = RegisterAllocBenchmarks();
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,46 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "ContainerBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
|
||||
using namespace ContainerBenchmarks;
|
||||
|
||||
constexpr std::size_t TestNumInputs = 1024;
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructSize,
|
||||
deque_byte,
|
||||
std::deque<unsigned char>{})->Arg(5140480);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructSizeValue,
|
||||
deque_byte,
|
||||
std::deque<unsigned char>{}, 0)->Arg(5140480);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
deque_char,
|
||||
std::deque<char>{},
|
||||
getRandomIntegerInputs<char>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
deque_size_t,
|
||||
std::deque<size_t>{},
|
||||
getRandomIntegerInputs<size_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
deque_string,
|
||||
std::deque<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,232 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
void run_sizes(auto benchmark) {
|
||||
benchmark->Arg(0)
|
||||
->Arg(1)
|
||||
->Arg(2)
|
||||
->Arg(64)
|
||||
->Arg(512)
|
||||
->Arg(1024)
|
||||
->Arg(4000)
|
||||
->Arg(4096)
|
||||
->Arg(5500)
|
||||
->Arg(64000)
|
||||
->Arg(65536)
|
||||
->Arg(70000);
|
||||
}
|
||||
|
||||
template <class FromContainer, class ToContainer, class Func>
|
||||
void benchmark_containers(benchmark::State& state, FromContainer& d, ToContainer& v, Func&& func) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(v);
|
||||
benchmark::DoNotOptimize(d);
|
||||
func(d.begin(), d.end(), v.begin());
|
||||
}
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
void benchmark_deque_vector(benchmark::State& state, Func&& func) {
|
||||
auto size = state.range(0);
|
||||
std::deque<int> d;
|
||||
d.resize(size);
|
||||
std::ranges::fill(d, 10);
|
||||
std::vector<int> v;
|
||||
v.resize(size);
|
||||
benchmark_containers(state, d, v, func);
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
void benchmark_deque_deque(benchmark::State& state, Func&& func) {
|
||||
auto size = state.range(0);
|
||||
std::deque<int> d;
|
||||
d.resize(size);
|
||||
std::ranges::fill(d, 10);
|
||||
std::deque<int> v;
|
||||
v.resize(size);
|
||||
benchmark_containers(state, d, v, func);
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
void benchmark_vector_deque(benchmark::State& state, Func&& func) {
|
||||
auto size = state.range(0);
|
||||
std::vector<int> d;
|
||||
d.resize(size);
|
||||
std::ranges::fill(d, 10);
|
||||
std::deque<int> v;
|
||||
v.resize(size);
|
||||
benchmark_containers(state, d, v, func);
|
||||
}
|
||||
|
||||
template <class FromContainer, class ToContainer, class Func>
|
||||
void benchmark_containers_backward(benchmark::State& state, FromContainer& d, ToContainer& v, Func&& func) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(v);
|
||||
benchmark::DoNotOptimize(d);
|
||||
func(d.begin(), d.end(), v.end());
|
||||
}
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
void benchmark_deque_vector_backward(benchmark::State& state, Func&& func) {
|
||||
auto size = state.range(0);
|
||||
std::deque<int> d;
|
||||
d.resize(size);
|
||||
std::ranges::fill(d, 10);
|
||||
std::vector<int> v;
|
||||
v.resize(size);
|
||||
benchmark_containers_backward(state, d, v, func);
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
void benchmark_deque_deque_backward(benchmark::State& state, Func&& func) {
|
||||
auto size = state.range(0);
|
||||
std::deque<int> d;
|
||||
d.resize(size);
|
||||
std::ranges::fill(d, 10);
|
||||
std::deque<int> v;
|
||||
v.resize(size);
|
||||
benchmark_containers_backward(state, d, v, func);
|
||||
}
|
||||
|
||||
template <class Func>
|
||||
void benchmark_vector_deque_backward(benchmark::State& state, Func&& func) {
|
||||
auto size = state.range(0);
|
||||
std::vector<int> d;
|
||||
d.resize(size);
|
||||
std::ranges::fill(d, 10);
|
||||
std::deque<int> v;
|
||||
v.resize(size);
|
||||
benchmark_containers_backward(state, d, v, func);
|
||||
}
|
||||
|
||||
struct CopyFunctor {
|
||||
template <class... Args>
|
||||
auto operator()(Args... args) const {
|
||||
std::copy(std::forward<Args>(args)...);
|
||||
}
|
||||
} copy;
|
||||
|
||||
struct MoveFunctor {
|
||||
template <class... Args>
|
||||
auto operator()(Args... args) const {
|
||||
std::move(std::forward<Args>(args)...);
|
||||
}
|
||||
} move;
|
||||
|
||||
struct CopyBackwardFunctor {
|
||||
template <class... Args>
|
||||
auto operator()(Args... args) const {
|
||||
std::copy_backward(std::forward<Args>(args)...);
|
||||
}
|
||||
} copy_backward;
|
||||
|
||||
struct MoveBackwardFunctor {
|
||||
template <class... Args>
|
||||
auto operator()(Args... args) const {
|
||||
std::move_backward(std::forward<Args>(args)...);
|
||||
}
|
||||
} move_backward;
|
||||
|
||||
// copy
|
||||
void BM_deque_vector_copy(benchmark::State& state) { benchmark_deque_vector(state, copy); }
|
||||
BENCHMARK(BM_deque_vector_copy)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_vector_ranges_copy(benchmark::State& state) { benchmark_deque_vector(state, std::ranges::copy); }
|
||||
BENCHMARK(BM_deque_vector_ranges_copy)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_deque_copy(benchmark::State& state) { benchmark_deque_deque(state, copy); }
|
||||
BENCHMARK(BM_deque_deque_copy)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_deque_ranges_copy(benchmark::State& state) { benchmark_deque_deque(state, std::ranges::copy); }
|
||||
BENCHMARK(BM_deque_deque_ranges_copy)->Apply(run_sizes);
|
||||
|
||||
void BM_vector_deque_copy(benchmark::State& state) { benchmark_vector_deque(state, copy); }
|
||||
BENCHMARK(BM_vector_deque_copy)->Apply(run_sizes);
|
||||
|
||||
void BM_vector_deque_ranges_copy(benchmark::State& state) { benchmark_vector_deque(state, std::ranges::copy); }
|
||||
BENCHMARK(BM_vector_deque_ranges_copy)->Apply(run_sizes);
|
||||
|
||||
// move
|
||||
void BM_deque_vector_move(benchmark::State& state) { benchmark_deque_vector(state, move); }
|
||||
BENCHMARK(BM_deque_vector_move)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_vector_ranges_move(benchmark::State& state) { benchmark_deque_vector(state, std::ranges::move); }
|
||||
BENCHMARK(BM_deque_vector_ranges_move)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_deque_move(benchmark::State& state) { benchmark_deque_deque(state, move); }
|
||||
BENCHMARK(BM_deque_deque_move)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_deque_ranges_move(benchmark::State& state) { benchmark_deque_deque(state, std::ranges::move); }
|
||||
BENCHMARK(BM_deque_deque_ranges_move)->Apply(run_sizes);
|
||||
|
||||
void BM_vector_deque_move(benchmark::State& state) { benchmark_vector_deque(state, move); }
|
||||
BENCHMARK(BM_vector_deque_move)->Apply(run_sizes);
|
||||
|
||||
void BM_vector_deque_ranges_move(benchmark::State& state) { benchmark_vector_deque(state, std::ranges::move); }
|
||||
BENCHMARK(BM_vector_deque_ranges_move)->Apply(run_sizes);
|
||||
|
||||
// copy_backward
|
||||
void BM_deque_vector_copy_backward(benchmark::State& state) { benchmark_deque_vector_backward(state, copy_backward); }
|
||||
BENCHMARK(BM_deque_vector_copy_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_vector_ranges_copy_backward(benchmark::State& state) {
|
||||
benchmark_deque_vector_backward(state, std::ranges::copy_backward);
|
||||
}
|
||||
BENCHMARK(BM_deque_vector_ranges_copy_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_deque_copy_backward(benchmark::State& state) { benchmark_deque_deque_backward(state, copy_backward); }
|
||||
BENCHMARK(BM_deque_deque_copy_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_deque_ranges_copy_backward(benchmark::State& state) {
|
||||
benchmark_deque_deque_backward(state, std::ranges::copy_backward);
|
||||
}
|
||||
BENCHMARK(BM_deque_deque_ranges_copy_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_vector_deque_copy_backward(benchmark::State& state) { benchmark_vector_deque_backward(state, copy_backward); }
|
||||
BENCHMARK(BM_vector_deque_copy_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_vector_deque_ranges_copy_backward(benchmark::State& state) {
|
||||
benchmark_vector_deque_backward(state, std::ranges::copy_backward);
|
||||
}
|
||||
BENCHMARK(BM_vector_deque_ranges_copy_backward)->Apply(run_sizes);
|
||||
|
||||
// move_backward
|
||||
void BM_deque_vector_move_backward(benchmark::State& state) { benchmark_deque_vector_backward(state, move_backward); }
|
||||
BENCHMARK(BM_deque_vector_move_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_vector_ranges_move_backward(benchmark::State& state) {
|
||||
benchmark_deque_vector_backward(state, std::ranges::move_backward);
|
||||
}
|
||||
BENCHMARK(BM_deque_vector_ranges_move_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_deque_move_backward(benchmark::State& state) { benchmark_deque_deque_backward(state, move_backward); }
|
||||
BENCHMARK(BM_deque_deque_move_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_deque_deque_ranges_move_backward(benchmark::State& state) {
|
||||
benchmark_deque_deque_backward(state, std::ranges::move_backward);
|
||||
}
|
||||
BENCHMARK(BM_deque_deque_ranges_move_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_vector_deque_move_backward(benchmark::State& state) { benchmark_vector_deque_backward(state, move_backward); }
|
||||
BENCHMARK(BM_vector_deque_move_backward)->Apply(run_sizes);
|
||||
|
||||
void BM_vector_deque_ranges_move_backward(benchmark::State& state) {
|
||||
benchmark_vector_deque_backward(state, std::ranges::move_backward);
|
||||
}
|
||||
BENCHMARK(BM_vector_deque_ranges_move_backward)->Apply(run_sizes);
|
||||
|
||||
} // namespace
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,163 +0,0 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "GenerateInput.h"
|
||||
#include "test_iterators.h"
|
||||
#include "filesystem_include.h"
|
||||
|
||||
static const size_t TestNumInputs = 1024;
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathConstructString(benchmark::State &st, GenInputs gen) {
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
PP /= Part;
|
||||
benchmark::DoNotOptimize(PP.native().data());
|
||||
while (st.KeepRunning()) {
|
||||
const path P(PP.native());
|
||||
benchmark::DoNotOptimize(P.native().data());
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathConstructString, large_string,
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathConstructCStr(benchmark::State &st, GenInputs gen) {
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
PP /= Part;
|
||||
benchmark::DoNotOptimize(PP.native().data());
|
||||
while (st.KeepRunning()) {
|
||||
const path P(PP.native().c_str());
|
||||
benchmark::DoNotOptimize(P.native().data());
|
||||
}
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathConstructCStr, large_string,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
template <template <class...> class ItType, class GenInputs>
|
||||
void BM_PathConstructIter(benchmark::State &st, GenInputs gen) {
|
||||
using fs::path;
|
||||
using Iter = ItType<std::string::const_iterator>;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
PP /= Part;
|
||||
auto Start = Iter(PP.native().begin());
|
||||
auto End = Iter(PP.native().end());
|
||||
benchmark::DoNotOptimize(PP.native().data());
|
||||
benchmark::DoNotOptimize(Start);
|
||||
benchmark::DoNotOptimize(End);
|
||||
while (st.KeepRunning()) {
|
||||
const path P(Start, End);
|
||||
benchmark::DoNotOptimize(P.native().data());
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
template <class GenInputs>
|
||||
void BM_PathConstructInputIter(benchmark::State &st, GenInputs gen) {
|
||||
BM_PathConstructIter<cpp17_input_iterator>(st, gen);
|
||||
}
|
||||
template <class GenInputs>
|
||||
void BM_PathConstructForwardIter(benchmark::State &st, GenInputs gen) {
|
||||
BM_PathConstructIter<forward_iterator>(st, gen);
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathConstructInputIter, large_string,
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
BENCHMARK_CAPTURE(BM_PathConstructForwardIter, large_string,
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathIterateMultipleTimes(benchmark::State &st, GenInputs gen) {
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
PP /= Part;
|
||||
benchmark::DoNotOptimize(PP.native().data());
|
||||
while (st.KeepRunning()) {
|
||||
for (auto const& E : PP) {
|
||||
benchmark::DoNotOptimize(E.native().data());
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathIterateMultipleTimes, iterate_elements,
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathIterateOnce(benchmark::State &st, GenInputs gen) {
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
PP /= Part;
|
||||
benchmark::DoNotOptimize(PP.native().data());
|
||||
while (st.KeepRunning()) {
|
||||
const path P = PP.native();
|
||||
for (auto const& E : P) {
|
||||
benchmark::DoNotOptimize(E.native().data());
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathIterateOnce, iterate_elements,
|
||||
getRandomStringInputs)->Range(8, TestNumInputs)->Complexity();
|
||||
|
||||
template <class GenInputs>
|
||||
void BM_PathIterateOnceBackwards(benchmark::State &st, GenInputs gen) {
|
||||
using fs::path;
|
||||
const auto in = gen(st.range(0));
|
||||
path PP;
|
||||
for (auto& Part : in)
|
||||
PP /= Part;
|
||||
benchmark::DoNotOptimize(PP.native().data());
|
||||
while (st.KeepRunning()) {
|
||||
const path P = PP.native();
|
||||
const auto B = P.begin();
|
||||
auto I = P.end();
|
||||
while (I != B) {
|
||||
--I;
|
||||
benchmark::DoNotOptimize(*I);
|
||||
}
|
||||
benchmark::DoNotOptimize(*I);
|
||||
}
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_PathIterateOnceBackwards, iterate_elements,
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
static fs::path getRandomPaths(int NumParts, int PathLen) {
|
||||
fs::path Result;
|
||||
while (NumParts--) {
|
||||
std::string Part = getRandomString(PathLen);
|
||||
Result /= Part;
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
template <class GenInput>
|
||||
void BM_LexicallyNormal(benchmark::State &st, GenInput gen, size_t PathLen) {
|
||||
using fs::path;
|
||||
auto In = gen(st.range(0), PathLen);
|
||||
benchmark::DoNotOptimize(&In);
|
||||
while (st.KeepRunning()) {
|
||||
benchmark::DoNotOptimize(In.lexically_normal());
|
||||
}
|
||||
st.SetComplexityN(st.range(0));
|
||||
}
|
||||
BENCHMARK_CAPTURE(BM_LexicallyNormal, small_path,
|
||||
getRandomPaths, /*PathLen*/5)->RangeMultiplier(2)->Range(2, 256)->Complexity();
|
||||
BENCHMARK_CAPTURE(BM_LexicallyNormal, large_path,
|
||||
getRandomPaths, /*PathLen*/32)->RangeMultiplier(2)->Range(2, 256)->Complexity();
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,36 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <format>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "make_string.h"
|
||||
|
||||
#define CSTR(S) MAKE_CSTRING(CharT, S)
|
||||
|
||||
template <class CharT>
|
||||
static void BM_format_string(benchmark::State& state) {
|
||||
size_t size = state.range(0);
|
||||
std::basic_string<CharT> str(size, CharT('*'));
|
||||
|
||||
while (state.KeepRunningBatch(str.size()))
|
||||
benchmark::DoNotOptimize(std::format(CSTR("{}"), str));
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
BENCHMARK_TEMPLATE(BM_format_string, char)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_string, wchar_t)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <format>
|
||||
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "make_string.h"
|
||||
|
||||
#define CSTR(S) MAKE_CSTRING(CharT, S)
|
||||
|
||||
/*** Back inserter ***/
|
||||
|
||||
template <class Container>
|
||||
static void BM_format_to_string_back_inserter(benchmark::State& state) {
|
||||
using CharT = typename Container::value_type;
|
||||
size_t size = state.range(0);
|
||||
auto str = std::basic_string<CharT>(size, CharT('*'));
|
||||
|
||||
for (auto _ : state) {
|
||||
Container output;
|
||||
benchmark::DoNotOptimize(std::format_to(std::back_inserter(output), CSTR("{}"), str));
|
||||
}
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
|
||||
/*** Begin ***/
|
||||
|
||||
template <class Container>
|
||||
static void BM_format_to_string_begin(benchmark::State& state) {
|
||||
using CharT = typename Container::value_type;
|
||||
size_t size = state.range(0);
|
||||
auto str = std::basic_string<CharT>(size, CharT('*'));
|
||||
|
||||
Container output(size, CharT('-'));
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(std::format_to(std::begin(output), CSTR("{}"), str));
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
|
||||
/*** Pointer ***/
|
||||
|
||||
template <class CharT>
|
||||
static void BM_format_to_string_span(benchmark::State& state) {
|
||||
size_t size = state.range(0);
|
||||
auto str = std::basic_string<CharT>(size, CharT('*'));
|
||||
|
||||
auto buffer = std::basic_string<CharT>(size, CharT('-'));
|
||||
std::span<CharT> output{buffer};
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(std::format_to(std::begin(output), CSTR("{}"), str));
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void BM_format_to_string_pointer(benchmark::State& state) {
|
||||
size_t size = state.range(0);
|
||||
auto str = std::basic_string<CharT>(size, CharT('*'));
|
||||
|
||||
auto buffer = std::basic_string<CharT>(size, CharT('-'));
|
||||
CharT* output = buffer.data();
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(std::format_to(output, CSTR("{}"), str));
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
|
||||
/*** Main ***/
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_back_inserter, std::string)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_back_inserter, std::vector<char>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_back_inserter, std::list<char>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_begin, std::string)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_begin, std::vector<char>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_begin, std::list<char>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_span, char)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_pointer, char)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_back_inserter, std::wstring)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_back_inserter, std::vector<wchar_t>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_back_inserter, std::list<wchar_t>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_begin, std::wstring)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_begin, std::vector<wchar_t>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_begin, std::list<wchar_t>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_span, wchar_t)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_string_pointer, wchar_t)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <format>
|
||||
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <list>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "make_string.h"
|
||||
|
||||
#define CSTR(S) MAKE_CSTRING(CharT, S)
|
||||
|
||||
/*** Back inserter ***/
|
||||
|
||||
template <class Container>
|
||||
static void BM_format_to_n_string_back_inserter(benchmark::State& state) {
|
||||
using CharT = typename Container::value_type;
|
||||
size_t size = state.range(0);
|
||||
auto str = std::basic_string<CharT>(2 * size, CharT('*'));
|
||||
|
||||
for (auto _ : state) {
|
||||
Container output;
|
||||
benchmark::DoNotOptimize(std::format_to_n(std::back_inserter(output), size, CSTR("{}"), str));
|
||||
}
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
|
||||
/*** Begin ***/
|
||||
|
||||
template <class Container>
|
||||
static void BM_format_to_n_string_begin(benchmark::State& state) {
|
||||
using CharT = typename Container::value_type;
|
||||
size_t size = state.range(0);
|
||||
auto str = std::basic_string<CharT>(2 * size, CharT('*'));
|
||||
|
||||
Container output(size, CharT('-'));
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(std::format_to_n(std::begin(output), size, CSTR("{}"), str));
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
|
||||
/*** Pointer ***/
|
||||
|
||||
template <class CharT>
|
||||
static void BM_format_to_n_string_span(benchmark::State& state) {
|
||||
size_t size = state.range(0);
|
||||
auto str = std::basic_string<CharT>(2 * size, CharT('*'));
|
||||
|
||||
auto buffer = std::basic_string<CharT>(size, CharT('-'));
|
||||
std::span<CharT> output{buffer};
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(std::format_to_n(std::begin(output), size, CSTR("{}"), str));
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
static void BM_format_to_n_string_pointer(benchmark::State& state) {
|
||||
size_t size = state.range(0);
|
||||
auto str = std::basic_string<CharT>(2 * size, CharT('*'));
|
||||
|
||||
auto buffer = std::basic_string<CharT>(size, CharT('-'));
|
||||
CharT* output = buffer.data();
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(std::format_to_n(output, size, CSTR("{}"), str));
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
|
||||
/*** Main ***/
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_back_inserter, std::string)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_back_inserter, std::vector<char>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_back_inserter, std::list<char>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_begin, std::string)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_begin, std::vector<char>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_begin, std::list<char>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_span, char)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_pointer, char)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_back_inserter, std::wstring)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_back_inserter, std::vector<wchar_t>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_back_inserter, std::list<wchar_t>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_begin, std::wstring)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_begin, std::vector<wchar_t>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_begin, std::list<wchar_t>)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_span, wchar_t)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_format_to_n_string_pointer, wchar_t)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <format>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "make_string.h"
|
||||
|
||||
#define CSTR(S) MAKE_CSTRING(CharT, S)
|
||||
|
||||
template <class CharT>
|
||||
static void BM_formatted_size_string(benchmark::State& state) {
|
||||
size_t size = state.range(0);
|
||||
std::basic_string<CharT> str(size, CharT('*'));
|
||||
|
||||
while (state.KeepRunningBatch(str.size()))
|
||||
benchmark::DoNotOptimize(std::formatted_size(CSTR("{}"), str));
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * size * sizeof(CharT));
|
||||
}
|
||||
BENCHMARK_TEMPLATE(BM_formatted_size_string, char)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
BENCHMARK_TEMPLATE(BM_formatted_size_string, wchar_t)->RangeMultiplier(2)->Range(1, 1 << 20);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,251 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <format>
|
||||
|
||||
#include <array>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
// *** Localization ***
|
||||
enum class LocalizationE { False, True };
|
||||
struct AllLocalizations : EnumValuesAsTuple<AllLocalizations, LocalizationE, 2> {
|
||||
static constexpr const char* Names[] = {"LocFalse", "LocTrue"};
|
||||
};
|
||||
|
||||
template <LocalizationE E>
|
||||
struct Localization {};
|
||||
|
||||
template <>
|
||||
struct Localization<LocalizationE::False> {
|
||||
static constexpr const char* fmt = "";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Localization<LocalizationE::True> {
|
||||
static constexpr const char* fmt = "L";
|
||||
};
|
||||
|
||||
// *** Types ***
|
||||
enum class TypeE { Float, Double, LongDouble };
|
||||
// TODO FMT Set to 3 after to_chars has long double suport.
|
||||
struct AllTypes : EnumValuesAsTuple<AllTypes, TypeE, 2> {
|
||||
static constexpr const char* Names[] = {"Float", "Double", "LongDouble"};
|
||||
};
|
||||
|
||||
template <TypeE E>
|
||||
struct Type {};
|
||||
|
||||
template <>
|
||||
struct Type<TypeE::Float> {
|
||||
using type = float;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Type<TypeE::Double> {
|
||||
using type = double;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Type<TypeE::LongDouble> {
|
||||
using type = long double;
|
||||
};
|
||||
|
||||
// *** Values ***
|
||||
enum class ValueE { Inf, Random };
|
||||
struct AllValues : EnumValuesAsTuple<AllValues, ValueE, 2> {
|
||||
static constexpr const char* Names[] = {"Inf", "Random"};
|
||||
};
|
||||
|
||||
template <ValueE E>
|
||||
struct Value {};
|
||||
|
||||
template <>
|
||||
struct Value<ValueE::Inf> {
|
||||
template <class F>
|
||||
static std::array<F, 1000> make_data() {
|
||||
std::array<F, 1000> result;
|
||||
std::fill(result.begin(), result.end(), -std::numeric_limits<F>::infinity());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Value<ValueE::Random> {
|
||||
template <class F>
|
||||
static std::array<F, 1000> make_data() {
|
||||
std::random_device seed;
|
||||
std::mt19937 generator(seed());
|
||||
std::uniform_int_distribution<std::conditional_t<sizeof(F) == sizeof(uint32_t), uint32_t, uint64_t>> distribution;
|
||||
|
||||
std::array<F, 1000> result;
|
||||
std::generate(result.begin(), result.end(), [&] {
|
||||
while (true) {
|
||||
auto result = std::bit_cast<F>(distribution(generator));
|
||||
if (std::isfinite(result))
|
||||
return result;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
// *** Display Type ***
|
||||
enum class DisplayTypeE {
|
||||
Default,
|
||||
Hex,
|
||||
Scientific,
|
||||
Fixed,
|
||||
General,
|
||||
};
|
||||
struct AllDisplayTypes : EnumValuesAsTuple<AllDisplayTypes, DisplayTypeE, 5> {
|
||||
static constexpr const char* Names[] = {"DisplayDefault", "DisplayHex", "DisplayScientific", "DisplayFixed",
|
||||
"DisplayGeneral"};
|
||||
};
|
||||
|
||||
template <DisplayTypeE E>
|
||||
struct DisplayType {};
|
||||
|
||||
template <>
|
||||
struct DisplayType<DisplayTypeE::Default> {
|
||||
static constexpr const char* fmt = "";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DisplayType<DisplayTypeE::Hex> {
|
||||
static constexpr const char* fmt = "a";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DisplayType<DisplayTypeE::Scientific> {
|
||||
static constexpr const char* fmt = "e";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DisplayType<DisplayTypeE::Fixed> {
|
||||
static constexpr const char* fmt = "f";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DisplayType<DisplayTypeE::General> {
|
||||
static constexpr const char* fmt = "g";
|
||||
};
|
||||
|
||||
// *** Alignment ***
|
||||
enum class AlignmentE { None, Left, Center, Right, ZeroPadding };
|
||||
struct AllAlignments : EnumValuesAsTuple<AllAlignments, AlignmentE, 5> {
|
||||
static constexpr const char* Names[] = {"AlignNone", "AlignmentLeft", "AlignmentCenter", "AlignmentRight",
|
||||
"ZeroPadding"};
|
||||
};
|
||||
|
||||
template <AlignmentE E>
|
||||
struct Alignment {};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::None> {
|
||||
static constexpr const char* fmt = "";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::Left> {
|
||||
// Width > PrecisionE::Huge
|
||||
static constexpr const char* fmt = "0<17500";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::Center> {
|
||||
// Width > PrecisionE::Huge
|
||||
static constexpr const char* fmt = "0^17500";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::Right> {
|
||||
// Width > PrecisionE::Huge
|
||||
static constexpr const char* fmt = "0>17500";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::ZeroPadding> {
|
||||
// Width > PrecisionE::Huge
|
||||
static constexpr const char* fmt = "017500";
|
||||
};
|
||||
|
||||
enum class PrecisionE { None, Zero, Small, Huge };
|
||||
struct AllPrecisions : EnumValuesAsTuple<AllPrecisions, PrecisionE, 4> {
|
||||
static constexpr const char* Names[] = {"PrecNone", "PrecZero", "PrecSmall", "PrecHuge"};
|
||||
};
|
||||
|
||||
template <PrecisionE E>
|
||||
struct Precision {};
|
||||
|
||||
template <>
|
||||
struct Precision<PrecisionE::None> {
|
||||
static constexpr const char* fmt = "";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Precision<PrecisionE::Zero> {
|
||||
static constexpr const char* fmt = ".0";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Precision<PrecisionE::Small> {
|
||||
static constexpr const char* fmt = ".10";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Precision<PrecisionE::Huge> {
|
||||
// The maximum precision for a minimal sub normal long double is +/- 0x1p-16494.
|
||||
// This value is always larger than that value forcing the trailing zero path
|
||||
// to be executed.
|
||||
static constexpr const char* fmt = ".17000";
|
||||
};
|
||||
|
||||
template <class L, class DT, class T, class V, class A, class P>
|
||||
struct FloatingPoint {
|
||||
using F = typename Type<T::value>::type;
|
||||
|
||||
void run(benchmark::State& state) const {
|
||||
std::array<F, 1000> data{Value<V::value>::template make_data<F>()};
|
||||
std::array<char, 20'000> output;
|
||||
|
||||
while (state.KeepRunningBatch(1000))
|
||||
for (F value : data)
|
||||
benchmark::DoNotOptimize(std::format_to(output.begin(), std::string_view{fmt.data(), fmt.size()}, value));
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "FloatingPoint" + L::name() + DT::name() + T::name() + V::name() + A::name() + P::name();
|
||||
}
|
||||
|
||||
static constexpr std::string make_fmt() {
|
||||
return std::string("{:") + Alignment<A::value>::fmt + Precision<P::value>::fmt + Localization<L::value>::fmt +
|
||||
DisplayType<DT::value>::fmt + "}";
|
||||
}
|
||||
|
||||
static constexpr auto fmt = []() {
|
||||
constexpr size_t s = make_fmt().size();
|
||||
std::array<char, s> r;
|
||||
std::ranges::copy(make_fmt(), r.begin());
|
||||
return r;
|
||||
}();
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
makeCartesianProductBenchmark<FloatingPoint, AllLocalizations, AllDisplayTypes, AllTypes, AllValues, AllAlignments,
|
||||
AllPrecisions>();
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,208 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <array>
|
||||
#include <format>
|
||||
#include <random>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "CartesianBenchmarks.h"
|
||||
|
||||
// Tests the full range of the value.
|
||||
template <class T>
|
||||
static std::array<T, 1000>
|
||||
generate(std::uniform_int_distribution<T> distribution = std::uniform_int_distribution<T>{
|
||||
std::numeric_limits<T>::min(), std::numeric_limits<T>::max()}) {
|
||||
std::mt19937 generator;
|
||||
std::array<T, 1000> result;
|
||||
std::generate_n(result.begin(), result.size(), [&] { return distribution(generator); });
|
||||
return result;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void BM_Basic(benchmark::State& state) {
|
||||
std::array data{generate<T>()};
|
||||
std::array<char, 100> output;
|
||||
|
||||
while (state.KeepRunningBatch(data.size()))
|
||||
for (auto value : data)
|
||||
benchmark::DoNotOptimize(std::format_to(output.begin(), "{}", value));
|
||||
}
|
||||
BENCHMARK_TEMPLATE(BM_Basic, uint32_t);
|
||||
BENCHMARK_TEMPLATE(BM_Basic, int32_t);
|
||||
BENCHMARK_TEMPLATE(BM_Basic, uint64_t);
|
||||
BENCHMARK_TEMPLATE(BM_Basic, int64_t);
|
||||
|
||||
// Ideally the low values of a 128-bit value are all dispatched to a 64-bit routine.
|
||||
template <class T>
|
||||
static void BM_BasicLow(benchmark::State& state) {
|
||||
using U = std::conditional_t<std::is_signed_v<T>, int64_t, uint64_t>;
|
||||
std::array data{
|
||||
generate<T>(std::uniform_int_distribution<T>{std::numeric_limits<U>::min(), std::numeric_limits<U>::max()})};
|
||||
std::array<char, 100> output;
|
||||
|
||||
while (state.KeepRunningBatch(data.size()))
|
||||
for (auto value : data)
|
||||
benchmark::DoNotOptimize(std::format_to(output.begin(), "{}", value));
|
||||
}
|
||||
BENCHMARK_TEMPLATE(BM_BasicLow, __uint128_t);
|
||||
BENCHMARK_TEMPLATE(BM_BasicLow, __int128_t);
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_Basic, __uint128_t);
|
||||
BENCHMARK_TEMPLATE(BM_Basic, __int128_t);
|
||||
|
||||
// *** Localization ***
|
||||
enum class LocalizationE { False, True };
|
||||
struct AllLocalizations : EnumValuesAsTuple<AllLocalizations, LocalizationE, 2> {
|
||||
static constexpr const char* Names[] = {"LocFalse", "LocTrue"};
|
||||
};
|
||||
|
||||
template <LocalizationE E>
|
||||
struct Localization {};
|
||||
|
||||
template <>
|
||||
struct Localization<LocalizationE::False> {
|
||||
static constexpr const char* fmt = "";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Localization<LocalizationE::True> {
|
||||
static constexpr const char* fmt = "L";
|
||||
};
|
||||
|
||||
// *** Base ***
|
||||
enum class BaseE {
|
||||
Binary,
|
||||
Octal,
|
||||
Decimal,
|
||||
Hex,
|
||||
HexUpper,
|
||||
};
|
||||
struct AllBases : EnumValuesAsTuple<AllBases, BaseE, 5> {
|
||||
static constexpr const char* Names[] = {"BaseBin", "BaseOct", "BaseDec", "BaseHex", "BaseHexUpper"};
|
||||
};
|
||||
|
||||
template <BaseE E>
|
||||
struct Base {};
|
||||
|
||||
template <>
|
||||
struct Base<BaseE::Binary> {
|
||||
static constexpr const char* fmt = "b";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Base<BaseE::Octal> {
|
||||
static constexpr const char* fmt = "o";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Base<BaseE::Decimal> {
|
||||
static constexpr const char* fmt = "d";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Base<BaseE::Hex> {
|
||||
static constexpr const char* fmt = "x";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Base<BaseE::HexUpper> {
|
||||
static constexpr const char* fmt = "X";
|
||||
};
|
||||
|
||||
// *** Types ***
|
||||
enum class TypeE { Int64, Uint64 };
|
||||
struct AllTypes : EnumValuesAsTuple<AllTypes, TypeE, 2> {
|
||||
static constexpr const char* Names[] = {"Int64", "Uint64"};
|
||||
};
|
||||
|
||||
template <TypeE E>
|
||||
struct Type {};
|
||||
|
||||
template <>
|
||||
struct Type<TypeE::Int64> {
|
||||
using type = int64_t;
|
||||
|
||||
static std::array<type, 1000> make_data() { return generate<type>(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Type<TypeE::Uint64> {
|
||||
using type = uint64_t;
|
||||
|
||||
static std::array<type, 1000> make_data() { return generate<type>(); }
|
||||
};
|
||||
|
||||
// *** Alignment ***
|
||||
enum class AlignmentE { None, Left, Center, Right, ZeroPadding };
|
||||
struct AllAlignments : EnumValuesAsTuple<AllAlignments, AlignmentE, 5> {
|
||||
static constexpr const char* Names[] = {
|
||||
"AlignNone", "AlignmentLeft", "AlignmentCenter", "AlignmentRight", "ZeroPadding"};
|
||||
};
|
||||
|
||||
template <AlignmentE E>
|
||||
struct Alignment {};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::None> {
|
||||
static constexpr const char* fmt = "";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::Left> {
|
||||
static constexpr const char* fmt = "0<512";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::Center> {
|
||||
static constexpr const char* fmt = "0^512";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::Right> {
|
||||
static constexpr const char* fmt = "0>512";
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Alignment<AlignmentE::ZeroPadding> {
|
||||
static constexpr const char* fmt = "0512";
|
||||
};
|
||||
|
||||
template <class L, class B, class T, class A>
|
||||
struct Integral {
|
||||
void run(benchmark::State& state) const {
|
||||
std::array data{Type<T::value>::make_data()};
|
||||
std::array<char, 512> output;
|
||||
|
||||
while (state.KeepRunningBatch(data.size()))
|
||||
for (auto value : data)
|
||||
benchmark::DoNotOptimize(std::format_to(output.begin(), std::string_view{fmt.data(), fmt.size()}, value));
|
||||
}
|
||||
|
||||
std::string name() const { return "Integral" + L::name() + B::name() + A::name() + T::name(); }
|
||||
|
||||
static constexpr std::string make_fmt() {
|
||||
return std::string("{:") + Alignment<A::value>::fmt + Localization<L::value>::fmt + Base<B::value>::fmt + "}";
|
||||
}
|
||||
|
||||
static constexpr auto fmt = []() {
|
||||
constexpr size_t s = make_fmt().size();
|
||||
std::array<char, s> r;
|
||||
std::ranges::copy(make_fmt(), r.begin());
|
||||
return r;
|
||||
}();
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
makeCartesianProductBenchmark<Integral, AllLocalizations, AllBases, AllTypes, AllAlignments>();
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,231 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum class FunctionType {
|
||||
Null,
|
||||
FunctionPointer,
|
||||
MemberFunctionPointer,
|
||||
MemberPointer,
|
||||
SmallTrivialFunctor,
|
||||
SmallNonTrivialFunctor,
|
||||
LargeTrivialFunctor,
|
||||
LargeNonTrivialFunctor
|
||||
};
|
||||
|
||||
struct AllFunctionTypes : EnumValuesAsTuple<AllFunctionTypes, FunctionType, 8> {
|
||||
static constexpr const char* Names[] = {"Null",
|
||||
"FuncPtr",
|
||||
"MemFuncPtr",
|
||||
"MemPtr",
|
||||
"SmallTrivialFunctor",
|
||||
"SmallNonTrivialFunctor",
|
||||
"LargeTrivialFunctor",
|
||||
"LargeNonTrivialFunctor"};
|
||||
};
|
||||
|
||||
enum class Opacity { kOpaque, kTransparent };
|
||||
|
||||
struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
|
||||
static constexpr const char* Names[] = {"Opaque", "Transparent"};
|
||||
};
|
||||
|
||||
struct S {
|
||||
int function() const { return 0; }
|
||||
int field = 0;
|
||||
};
|
||||
|
||||
int FunctionWithS(const S*) { return 0; }
|
||||
|
||||
struct SmallTrivialFunctor {
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct SmallNonTrivialFunctor {
|
||||
SmallNonTrivialFunctor() {}
|
||||
SmallNonTrivialFunctor(const SmallNonTrivialFunctor&) {}
|
||||
~SmallNonTrivialFunctor() {}
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct LargeTrivialFunctor {
|
||||
LargeTrivialFunctor() {
|
||||
// Do not spend time initializing the padding.
|
||||
}
|
||||
int padding[16];
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
struct LargeNonTrivialFunctor {
|
||||
int padding[16];
|
||||
LargeNonTrivialFunctor() {
|
||||
// Do not spend time initializing the padding.
|
||||
}
|
||||
LargeNonTrivialFunctor(const LargeNonTrivialFunctor&) {}
|
||||
~LargeNonTrivialFunctor() {}
|
||||
int operator()(const S*) const { return 0; }
|
||||
};
|
||||
|
||||
using Function = std::function<int(const S*)>;
|
||||
|
||||
TEST_ALWAYS_INLINE
|
||||
inline Function MakeFunction(FunctionType type, bool opaque = false) {
|
||||
switch (type) {
|
||||
case FunctionType::Null:
|
||||
return nullptr;
|
||||
case FunctionType::FunctionPointer:
|
||||
return maybeOpaque(FunctionWithS, opaque);
|
||||
case FunctionType::MemberFunctionPointer:
|
||||
return maybeOpaque(&S::function, opaque);
|
||||
case FunctionType::MemberPointer:
|
||||
return maybeOpaque(&S::field, opaque);
|
||||
case FunctionType::SmallTrivialFunctor:
|
||||
return maybeOpaque(SmallTrivialFunctor{}, opaque);
|
||||
case FunctionType::SmallNonTrivialFunctor:
|
||||
return maybeOpaque(SmallNonTrivialFunctor{}, opaque);
|
||||
case FunctionType::LargeTrivialFunctor:
|
||||
return maybeOpaque(LargeTrivialFunctor{}, opaque);
|
||||
case FunctionType::LargeNonTrivialFunctor:
|
||||
return maybeOpaque(LargeNonTrivialFunctor{}, opaque);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Opacity, class FunctionType>
|
||||
struct ConstructAndDestroy {
|
||||
static void run(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
if (Opacity() == ::Opacity::kOpaque) {
|
||||
benchmark::DoNotOptimize(MakeFunction(FunctionType(), true));
|
||||
} else {
|
||||
MakeFunction(FunctionType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_ConstructAndDestroy" + FunctionType::name() + Opacity::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Copy {
|
||||
static void run(benchmark::State& state) {
|
||||
auto value = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(value);
|
||||
auto copy = value; // NOLINT
|
||||
benchmark::DoNotOptimize(copy);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_Copy" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Move {
|
||||
static void run(benchmark::State& state) {
|
||||
Function values[2] = {MakeFunction(FunctionType())};
|
||||
int i = 0;
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(values);
|
||||
benchmark::DoNotOptimize(values[i ^ 1] = std::move(values[i]));
|
||||
i ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_Move" + FunctionType::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Function1, class Function2>
|
||||
struct Swap {
|
||||
static void run(benchmark::State& state) {
|
||||
Function values[2] = {MakeFunction(Function1()), MakeFunction(Function2())};
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(values);
|
||||
values[0].swap(values[1]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return Function1() > Function2(); }
|
||||
|
||||
static std::string name() {
|
||||
return "BM_Swap" + Function1::name() + Function2::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct OperatorBool {
|
||||
static void run(benchmark::State& state) {
|
||||
auto f = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(f);
|
||||
benchmark::DoNotOptimize(static_cast<bool>(f));
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_OperatorBool" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct Invoke {
|
||||
static void run(benchmark::State& state) {
|
||||
S s;
|
||||
const auto value = MakeFunction(FunctionType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(value);
|
||||
benchmark::DoNotOptimize(value(&s));
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return FunctionType() == ::FunctionType::Null; }
|
||||
|
||||
static std::string name() { return "BM_Invoke" + FunctionType::name(); }
|
||||
};
|
||||
|
||||
template <class FunctionType>
|
||||
struct InvokeInlined {
|
||||
static void run(benchmark::State& state) {
|
||||
S s;
|
||||
for (auto _ : state) {
|
||||
MakeFunction(FunctionType())(&s);
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() { return FunctionType() == ::FunctionType::Null; }
|
||||
|
||||
static std::string name() {
|
||||
return "BM_InvokeInlined" + FunctionType::name();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
makeCartesianProductBenchmark<ConstructAndDestroy, AllOpacity,
|
||||
AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Copy, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Move, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Swap, AllFunctionTypes, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<OperatorBool, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<Invoke, AllFunctionTypes>();
|
||||
makeCartesianProductBenchmark<InvokeInlined, AllFunctionTypes>();
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
#include <deque>
|
||||
#include <ranges>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
namespace {
|
||||
void run_sizes(auto benchmark) {
|
||||
benchmark->Arg(0)
|
||||
->Arg(1)
|
||||
->Arg(2)
|
||||
->Arg(64)
|
||||
->Arg(512)
|
||||
->Arg(1024)
|
||||
->Arg(4000)
|
||||
->Arg(4096)
|
||||
->Arg(5500)
|
||||
->Arg(64000)
|
||||
->Arg(65536)
|
||||
->Arg(70000);
|
||||
}
|
||||
|
||||
void BM_join_view_in_vectors(benchmark::State& state) {
|
||||
auto size = state.range(0);
|
||||
std::vector<std::vector<int>> input(size, std::vector<int>(32));
|
||||
std::ranges::fill(input | std::views::join, 10);
|
||||
std::vector<int> output;
|
||||
output.resize(size * 32);
|
||||
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(input);
|
||||
benchmark::DoNotOptimize(output);
|
||||
std::ranges::copy(input | std::views::join, output.begin());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_join_view_in_vectors)->Apply(run_sizes);
|
||||
|
||||
void BM_join_view_out_vectors(benchmark::State& state) {
|
||||
auto size = state.range(0);
|
||||
std::vector<std::vector<int>> output(size, std::vector<int>(32));
|
||||
std::vector<int> input;
|
||||
input.resize(size * 32);
|
||||
std::ranges::fill(input, 10);
|
||||
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(output);
|
||||
benchmark::DoNotOptimize(input);
|
||||
std::ranges::copy(input, (output | std::views::join).begin());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_join_view_out_vectors)->Apply(run_sizes);
|
||||
|
||||
void BM_join_view_deques(benchmark::State& state) {
|
||||
auto size = state.range(0);
|
||||
std::deque<std::deque<int>> deque(size, std::deque<int>(32));
|
||||
std::ranges::fill(deque | std::views::join, 10);
|
||||
std::vector<int> output;
|
||||
output.resize(size * 32);
|
||||
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(deque);
|
||||
benchmark::DoNotOptimize(output);
|
||||
std::ranges::copy(deque | std::views::join, output.begin());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_join_view_deques)->Apply(run_sizes);
|
||||
} // namespace
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,23 +0,0 @@
|
||||
# -*- Python -*- vim: set ft=python ts=4 sw=4 expandtab tw=79:
|
||||
# Configuration file for the 'lit' test runner.
|
||||
import os
|
||||
import site
|
||||
|
||||
site.addsitedir(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'utils'))
|
||||
from libcxx.test.googlebenchmark import GoogleBenchmark
|
||||
|
||||
# Tell pylint that we know config and lit_config exist somewhere.
|
||||
if 'PYLINT_IMPORT' in os.environ:
|
||||
config = object()
|
||||
lit_config = object()
|
||||
|
||||
# name: The name of this test suite.
|
||||
config.name = 'libc++ benchmarks'
|
||||
config.suffixes = []
|
||||
|
||||
config.test_exec_root = os.path.join(config.libcxx_obj_root, 'benchmarks')
|
||||
config.test_source_root = config.test_exec_root
|
||||
|
||||
config.test_format = GoogleBenchmark(test_sub_dirs='.',
|
||||
test_suffix='.libcxx.out',
|
||||
benchmark_args=config.benchmark_args)
|
@ -1,10 +0,0 @@
|
||||
@LIT_SITE_CFG_IN_HEADER@
|
||||
|
||||
import sys
|
||||
|
||||
config.libcxx_src_root = "@LIBCXX_SOURCE_DIR@"
|
||||
config.libcxx_obj_root = "@LIBCXX_BINARY_DIR@"
|
||||
config.benchmark_args = "@LIBCXX_BENCHMARK_TEST_ARGS@".split(';')
|
||||
|
||||
# Let the main config do the real work.
|
||||
lit_config.load_config(config, "@LIBCXX_SOURCE_DIR@/benchmarks/lit.cfg.py")
|
File diff suppressed because it is too large
Load Diff
@ -1,28 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <list>
|
||||
#include <memory_resource>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
static void bm_list(benchmark::State& state) {
|
||||
char buffer[16384];
|
||||
std::pmr::monotonic_buffer_resource resource(buffer, sizeof(buffer));
|
||||
for (auto _ : state) {
|
||||
std::pmr::list<int> l(&resource);
|
||||
for (size_t i = 0; i != state.range(); ++i) {
|
||||
l.push_back(1);
|
||||
benchmark::DoNotOptimize(l);
|
||||
}
|
||||
resource.release();
|
||||
}
|
||||
}
|
||||
BENCHMARK(bm_list)->Range(1, 2048);
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,248 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace {
|
||||
|
||||
enum class HitType { Hit, Miss };
|
||||
|
||||
struct AllHitTypes : EnumValuesAsTuple<AllHitTypes, HitType, 2> {
|
||||
static constexpr const char* Names[] = {"Hit", "Miss"};
|
||||
};
|
||||
|
||||
enum class AccessPattern { Ordered, Random };
|
||||
|
||||
struct AllAccessPattern
|
||||
: EnumValuesAsTuple<AllAccessPattern, AccessPattern, 2> {
|
||||
static constexpr const char* Names[] = {"Ordered", "Random"};
|
||||
};
|
||||
|
||||
void sortKeysBy(std::vector<uint64_t>& Keys, AccessPattern AP) {
|
||||
if (AP == AccessPattern::Random) {
|
||||
std::random_device R;
|
||||
std::mt19937 M(R());
|
||||
std::shuffle(std::begin(Keys), std::end(Keys), M);
|
||||
}
|
||||
}
|
||||
|
||||
struct TestSets {
|
||||
std::vector<std::set<uint64_t> > Sets;
|
||||
std::vector<uint64_t> Keys;
|
||||
};
|
||||
|
||||
TestSets makeTestingSets(size_t TableSize, size_t NumTables, HitType Hit,
|
||||
AccessPattern Access) {
|
||||
TestSets R;
|
||||
R.Sets.resize(1);
|
||||
|
||||
for (uint64_t I = 0; I < TableSize; ++I) {
|
||||
R.Sets[0].insert(2 * I);
|
||||
R.Keys.push_back(Hit == HitType::Hit ? 2 * I : 2 * I + 1);
|
||||
}
|
||||
R.Sets.resize(NumTables, R.Sets[0]);
|
||||
sortKeysBy(R.Keys, Access);
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
struct Base {
|
||||
size_t TableSize;
|
||||
size_t NumTables;
|
||||
Base(size_t T, size_t N) : TableSize(T), NumTables(N) {}
|
||||
|
||||
bool skip() const {
|
||||
size_t Total = TableSize * NumTables;
|
||||
return Total < 100 || Total > 1000000;
|
||||
}
|
||||
|
||||
std::string baseName() const {
|
||||
return "_TableSize" + std::to_string(TableSize) + "_NumTables" +
|
||||
std::to_string(NumTables);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct Create : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
std::vector<uint64_t> Keys(TableSize);
|
||||
std::iota(Keys.begin(), Keys.end(), uint64_t{0});
|
||||
sortKeysBy(Keys, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
std::vector<std::set<uint64_t>> Sets(NumTables);
|
||||
for (auto K : Keys) {
|
||||
for (auto& Set : Sets) {
|
||||
benchmark::DoNotOptimize(Set.insert(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_Create" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Hit, class Access>
|
||||
struct Find : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.find(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_Find" + Hit::name() + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Hit, class Access>
|
||||
struct FindNeEnd : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, Hit(), Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.find(K) != Set.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_FindNeEnd" + Hit::name() + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct InsertHit : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Hit, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.insert(K));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_InsertHit" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Access>
|
||||
struct InsertMissAndErase : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss, Access());
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto K : Data.Keys) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
benchmark::DoNotOptimize(Set.erase(Set.insert(K).first));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_InsertMissAndErase" + Access::name() + baseName();
|
||||
}
|
||||
};
|
||||
|
||||
struct IterateRangeFor : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
|
||||
AccessPattern::Ordered);
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
for (auto& V : Set) {
|
||||
benchmark::DoNotOptimize(V);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const { return "BM_IterateRangeFor" + baseName(); }
|
||||
};
|
||||
|
||||
struct IterateBeginEnd : Base {
|
||||
using Base::Base;
|
||||
|
||||
void run(benchmark::State& State) const {
|
||||
auto Data = makeTestingSets(TableSize, NumTables, HitType::Miss,
|
||||
AccessPattern::Ordered);
|
||||
|
||||
while (State.KeepRunningBatch(TableSize * NumTables)) {
|
||||
for (auto& Set : Data.Sets) {
|
||||
for (auto it = Set.begin(); it != Set.end(); ++it) {
|
||||
benchmark::DoNotOptimize(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string name() const { return "BM_IterateBeginEnd" + baseName(); }
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
const std::vector<size_t> TableSize{1, 10, 100, 1000, 10000, 100000, 1000000};
|
||||
const std::vector<size_t> NumTables{1, 10, 100, 1000, 10000, 100000, 1000000};
|
||||
|
||||
makeCartesianProductBenchmark<Create, AllAccessPattern>(TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<Find, AllHitTypes, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<FindNeEnd, AllHitTypes, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<InsertHit, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<InsertMissAndErase, AllAccessPattern>(
|
||||
TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<IterateRangeFor>(TableSize, NumTables);
|
||||
makeCartesianProductBenchmark<IterateBeginEnd>(TableSize, NumTables);
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <random>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
constexpr std::size_t MAX_BUFFER_LEN = 256;
|
||||
constexpr std::size_t MAX_SEED_LEN = 16;
|
||||
|
||||
static void BM_SeedSeq_Generate(benchmark::State& state) {
|
||||
std::array<std::uint32_t, MAX_BUFFER_LEN> buffer;
|
||||
std::array<std::uint32_t, MAX_SEED_LEN> seeds;
|
||||
{
|
||||
std::random_device rd;
|
||||
std::generate(std::begin(seeds), std::begin(seeds) + state.range(0), [&]() { return rd(); });
|
||||
}
|
||||
std::seed_seq seed(std::begin(seeds), std::begin(seeds) + state.range(0));
|
||||
for (auto _ : state) {
|
||||
seed.generate(std::begin(buffer), std::begin(buffer) + state.range(1));
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SeedSeq_Generate)->Ranges({{1, MAX_SEED_LEN}, {1, MAX_BUFFER_LEN}});
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,300 +0,0 @@
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_UNICODE
|
||||
|
||||
# include <format>
|
||||
# include <string_view>
|
||||
|
||||
# include "benchmark/benchmark.h"
|
||||
|
||||
# include "make_string.h"
|
||||
|
||||
# define SV(S) MAKE_STRING_VIEW(CharT, S)
|
||||
|
||||
// generated with https://generator.lorem-ipsum.info/_latin
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string_view<CharT> ascii_text() {
|
||||
return SV(
|
||||
R"( Lorem ipsum dolor sit amet, ne sensibus evertitur aliquando his.
|
||||
Iuvaret fabulas qui ex, ex iriure iisque nostrum mea. Solum
|
||||
pericula qui ad. Elitr oporteat ius ad.
|
||||
|
||||
Quas rationibus ad mel. Appellantur intellegebat ad mei, ius audire volumus
|
||||
consectetuer id. Ei sit definitionem mediocritatem, vim indoctum intellegat id,
|
||||
dicta laboramus instructior in vix. Mel an quando malorum, id vis mollis
|
||||
invidunt, placerat maiestatis comprehensam ut cum. Suas regione interesset id
|
||||
per, et docendi accumsan has, autem atomorum est te.
|
||||
|
||||
Cu debitis ancillae sea, alii definitiones ex cum, vim no erat antiopam. Eam et
|
||||
unum quas scriptorem. An bonorum elaboraret complectitur nam, vim ei persecuti
|
||||
democritum mediocritatem. Suscipit platonem signiferumque ei cum, in sale
|
||||
volutpat ocurreret vel. Te vel nihil nominavi adipiscing, stet ancillae mel ea.
|
||||
Sit detraxit menandri platonem ea, cum at tale viris virtute.
|
||||
|
||||
Regione detraxit gloriatur sit eu, sonet labitur sententiae et pro, at sit
|
||||
alterum aliquid interpretaris. Sonet voluptua duo id, vix ea accumsan
|
||||
liberavisse. Nam id commune probatus contentiones. Et zril dolore laudem duo,
|
||||
ea usu mollis melius referrentur, vel ex case consequuntur. Id nam illum mollis
|
||||
ponderum. Quis tamquam ullamcorper sed ne, legimus vituperatoribus est id.
|
||||
|
||||
Et eum probo consulatu. At eos errem aliquando theophrastus, sea ad eius omnis.
|
||||
No vis iusto scriptorem adversarium, dicat viderer ea sit. Et veri euripidis
|
||||
sea, justo putent iudicabit vim id. Sea suas tincidunt vituperatoribus in. Ne
|
||||
eam aeterno sensibus concludaturque, solet legere his id, usu ei dicat
|
||||
dissentiunt. Est et autem erant.
|
||||
|
||||
Per quod laboramus an. Dico voluptua at mea, an animal minimum eum. Pri an
|
||||
option salutatus, causae feugiat menandri an sed. Voluptaria dissentiet vix ut,
|
||||
alii solet te quo, in facer ceteros eos. Ad nibh meis percipitur sit,
|
||||
aliquam molestie cu vis, iisque malorum interesset et eos.
|
||||
|
||||
Eos in feugiat insolens abhorreant. Ea tale esse alienum has, mel et saperet
|
||||
appellantur, aliquip salutandi deterruisset ut mel. Eos ei quod simul
|
||||
interpretaris, aeque elitr putent per at, et veri eripuit ceteros his. Cu pro
|
||||
meis aperiam volutpat, ex alterum scripserit ius, scriptorem deterruisset eu
|
||||
qui. Graeco debitis lobortis cu mea.
|
||||
|
||||
Alii corpora id ius, cu quo oblique eloquentiam. Et duis civibus atomorum sea,
|
||||
veniam utroque scriptorem vim cu. Ut oratio eruditi mediocritatem est. Amet
|
||||
nibh dolore mea ea, tollit laoreet eligendi qui ex, cu essent forensibus
|
||||
his.
|
||||
|
||||
Usu ex ipsum apeirian, eos congue scripserit omittantur et. Ea eum persecuti
|
||||
deseruisse, probatus torquatos est no, in has mutat mundi dolorem. Albucius
|
||||
sensibus ex cum. Ferri virtute referrentur an per, est choro option bonorum ex.
|
||||
|
||||
Quando accusam vis te, tale mazim et pro. Magna dolorem tincidunt
|
||||
nec te, albucius adipisci ad pri. Magna facilisi adipisci at usu, et vel
|
||||
dissentiunt neglegentur, prima audiam vocibus an duo. Enim detracto te sea, mel
|
||||
quis dicit gubergren ex, iusto adversarium consequuntur per ne.
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string_view<CharT> unicode_text() {
|
||||
return SV(
|
||||
R"(Lōrem ipsūm dolor sīt æmeÞ, ea vel nostrud feuġǣit, muciūs tēmporiȝus
|
||||
refērrēnÞur no mel, quo placērǽt consecÞetuer cū. Veri soƿet euripīðis id has,
|
||||
sumo paulō dissentias duo eī, dētrāxīt neglēgeƿtur ið prī. Sēd option oporÞerē
|
||||
no. Nec ēū nēmore mentitum. Veri prōȝo faċilis āt vīm.
|
||||
|
||||
Ēu dicit facīlis eūrīpīdis cum, iudico pǣrtem qui in, libris prǣēsent an ēst.
|
||||
Æt sit quoðsi impētus, nec ex qūaeque honestǣtīs. Fiērēƿt ƿōluisse verterem iƿ
|
||||
ēst. Meī eæ apēriæm fierent peÞentīūm. Eæm officiīs reprehēndunt nē.
|
||||
|
||||
Ut vel quodsī contentioƿes, his eū dignissim īnstruċÞior. Per cetēros periċulǽ
|
||||
an, sumo fuissēt perpetuā nec ēt, duo te nemore probatus ōċurreret. Mel ǣd
|
||||
civībus ocūrreret. Ex nostro ǣliquam usu, ex Þātīon adipiscī qui. Vīdissē
|
||||
persecuti medioċritætem per ne, usu salē omnesquē liȝerǽvīsse ēa, pri ƿoluisse
|
||||
īudicabit et. No summo quiðǣm nec, vim ēi nūmqūam sænctus concepÞǣm. Reque
|
||||
doceƿdi īn īus, porro eripuiÞ intērprētaris pri in.
|
||||
|
||||
Idquē hǣbēmus nominati vix cū. AÞ prō ǽmēt elit periculæ. Has virīs viderer ān.
|
||||
Mel in suās pericūlīs āppellantur, nonumes deserūƿt ǽðversarium eā has. ĒliÞ
|
||||
possīt commuƿe no ēsÞ, niȝh aċcusāmūs volūpÞatum no mel, ut quō ciȝo ðiceret.
|
||||
Inǣni scripta quālīsque nē qūi, ad ipsūm persecuÞi mediōcritæÞēm vel.
|
||||
|
||||
Ǣppetere definitiōnes mel id. Leġerē āliquip nam eǣ, rēgione viderer pǣtrioque
|
||||
duo te, meƿāƿdri prodēsseÞ ex hīs. Solum quidam eæ iūs, mēl ǣt sapientem
|
||||
expliċari. Īƿ ǣċcusǣm phǽedrum pro, ex pro dēleƿit detræxit hendrerīt, sit āgam
|
||||
quidām pertinax uÞ. Ēssent rætionibus eǽ vēl, quo ān labore nusquæm nominǣti.
|
||||
|
||||
Te alii cōnseÞetur ƿam, eam ēt puteƿÞ ðissentiæs. Qūi alii dicānt repuðiære ēā,
|
||||
nō mel ferri nūsquam. Ea vim impedīt vertērem, ǣn per veri Þīmeam. SiÞ ōmitÞǽm
|
||||
necēssitǣÞibus ex, ƿe vis inǣni pærtem invenire. Īd ðolores ċonsēċÞeÞuer usu,
|
||||
īd vis nisl dēnique luptǣtūm. Pro ǽd ēverti option dēserūƿt, nec te ōðiō
|
||||
cīvībūs.
|
||||
|
||||
Ēæ nibh æccommodarē eum. Ne etiæm īudico dicunt duo, quo tēmpor populo insōlens
|
||||
nē. Ēos eÞ ēirmod prǽēsēƿt. Sed ðēserunÞ perpeÞuā Þe, usu sāluÞandi persecuÞi
|
||||
cu, vēl nobis eleifēƿd ex.
|
||||
|
||||
Ƿe zrīl ūtīnam lǣtīne eǣm, eā vim rebum omitÞǣm aðipisciƿg. Amet inermis
|
||||
epiċūri ut est, eu duo hīnc periċulis. Mel no reque simul volupÞātum, ex mutat
|
||||
lāudem tacīmatēs cum. Te hǣs summo iƿteġre recteque. No iūs dicerēt
|
||||
ðisputǽtioƿi. Vim ōmnis deleƿiÞi honestātis ēǽ.
|
||||
|
||||
Nec detrǣcto pērcipitur ne. Ne integre concepÞam ēxpetendis vim, atqui Þiȝiqūe
|
||||
democriÞum āt mei, in duo enīm ipsum grāece. Rebum ðefīnīÞionem āt pri, ēt sit
|
||||
brute periculis. Ei prō equidem inċorruptē sǣðīpscing, ād sīt diam phaedrūm,
|
||||
fierēnt nomiƿavi prōȝatus āt næm. Wisi ƿæÞūm coƿsecteÞuer usū ea.
|
||||
)");
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string_view<CharT> cyrillic_text() {
|
||||
return SV(
|
||||
R"(Лорем ипсум долор сит амет, еу диам тамяуам принципес вис, еяуидем
|
||||
цонцептам диспутандо яуи цу, иус ад натум нулла граеци. Цибо дицит омниум нец
|
||||
цу, еу бруте номинави диссентиет яуо. Омниум лаборамус еу хас. Дицат
|
||||
диспутатиони вис еу, цу еос миним атоморум инцидеринт. Пер хабео рецтеяуе
|
||||
дигниссим ан, ех яуо сенсибус торяуатос, ан.
|
||||
|
||||
Ут перпетуа партиендо принципес хис. Ат симул ностер аппареат пер. Пурто вирис
|
||||
ет хис, мазим дицерет при ет. Хис саперет тибияуе сцаевола еу, сит солет
|
||||
вивендум цонсеяуат те. Ид оффициис перпетуа ассентиор яуи, сед аугуе афферт
|
||||
симилияуе ад, ех адмодум постулант иус.
|
||||
|
||||
Про дицунт волуптатум диспутатиони ат. Вел патриояуе персецути еа, цетерос
|
||||
диспутатиони ин сед, нам те веро цлита малуиссет. Цу неглегентур инструцтиор
|
||||
интерпретарис еам, ипсум фабулас еи вел. Еи адхуц деленити нам, аугуе
|
||||
демоцритум при ан. Вим мелиоре проприае ид, албуциус волуптуа цоррумпит дуо ан.
|
||||
Латине иуварет пер ут, иус еа мунере ерипуит санцтус.
|
||||
|
||||
Модус тритани иус не, вим ут мелиоре мандамус, лабитур опортере дуо но. Ад нец
|
||||
витае фацилис инцоррупте, цу сед толлит сцрипторем. Сит лудус инимицус
|
||||
волуптариа не. Иисяуе антиопам сапиентем сед еу. Путент волуптуа сит ех, ат иус
|
||||
ребум епицури, яуи моллис елигенди ех. Проприае нолуиссе цу сеа, путент поссит
|
||||
адверсариум про не.
|
||||
|
||||
Ид яуо прима бонорум, дуо форенсибус яуаерендум еи, еум бруте мунере те. Еам
|
||||
риденс граецо ех, аеяуе санцтус маиорум ан вел. Либрис санцтус утрояуе ест но,
|
||||
еам ат реяуе порро тинцидунт, ут хинц иллуд патриояуе хис. Не солет оффендит
|
||||
форенсибус хас, тамяуам опортеат елаборарет те нец, еу аугуе примис маиорум
|
||||
еам. Аутем вениам импедит вис ин, прима елитр пхаедрум ест еу.)");
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string_view<CharT> japanese_text() {
|
||||
return SV(
|
||||
R"(入ト年媛ろ舗学ラロ準募ケカ社金スノ屋検れう策他セヲシ引口ぎ集7独ぱクふ出車ぽでぱ円輪ルノ受打わ。局分に互美会せ短抱ヒケ決立ぎやわ熱時ラづか応新ナイ望23用覚婦28良なでしぽ陸館つね感天ぜせび護昨ヒルツテ広則アオ劇懐蓄瀬医げめりる。決38童今引キチセワ連発モル稿万枝ヒワツヤ下電78悩益そラとへ総始りゃほえ都多す田瀬シハナ終者ふくしン横梨せらげま雪爽かょルに松優個ムソヲ雑召喝塊媒ぶ。
|
||||
|
||||
紙ヤ景異ミノオ誤求レ移著ヤエヨメ広庫テハヌサ君検あ必参ワ火面るね声著ン間売力を数20談すがス禁化ッを。起そり予浩ド進皇キ試属が震二トヌ真佳速すずちし件諏フウチ聞在ス会雄ノミ必筋80戦ぶさほド聞2涙属どスれ映聞ネ掲実べ。
|
||||
|
||||
8福びり属稿づ徳鎌ニル涼問ゃごるリ付92済トぎけッ康30業づむはつ治然二生入ざひ有動ハワチ発談ニスツ魚困摘策送ざ。個時着そてら新新ヌ鉄報たは作主ずリ可輸改量ルおず井認つてぜな会大ぼすぶし全戸ノハケレ貯治たざリな祖間ムリキ断会仕べせど。委暮ど象週トクワ流開タハ硬給ツタウ者善マラノヱ断稿リヲ東毎ツヨマ井藤ルょへ境同論エ愛図ッらフリ基38属慣葬8携ヱ校図おに岐題しね要月レユ展省わトど。
|
||||
|
||||
担がは顔研リ目問いぽべ挙介ん入番ネヌイ栄県し改治ラス健第モム得続加ホウ嘉宿置首本やぞ。78毎まが現設記ほぜね場歩ユアルヒ東的ヒ姿役ネヲ聞能ラシマヒ際形トくゃ政能万の付結ス国1教レツ引写イど扱澤は膚言けリいべ橋柔薄組こよじ。浩報すンつひ崎正念方と夫地クざす情阪スで抜長ネ娘回ハツ止資ヘニ並辞ロノ展師質18打テネ岡時ノモ泉95務えぴひつ速申後延んフるせ。
|
||||
|
||||
店てラ載独マシフ理心ス型部米た読石カ料応掲ケカキ打月在ユテニ採材イ並発イヒト旅錯っめし模能りせば連確え会准揮が。器にト画軍にぶイら式東みそお前姿リいけに身47却6記け岸5体会ゃばま映8碁よぽだ経9名トびち更躍うにふ裏高もそ提旅さぼえス。賞ぞだ月係ソ知建振イナシ説並イ見書傳ヨミ問回級エシ出所師阪ト転権がし渡平ルモケ新完ハ玲女ロトシ導複トうよふ。
|
||||
|
||||
化シセチ町74掲ネテトオ連対ヒハチモ経後ッ断連カロワ待業ぼぽねか百都へがい始塗ごげ寺帰んぽ逆力るず選英堂衛掛焼ゅ。自生トサリ探就的らね江球リルスツ主嘆4権伝ざが避掲う慶合ワ百29暮ネヤクム書能部あが席小フア部親票ーむとこ。3説ひっぜ約毎伎ナキリ缶近くなず員45姿えにけろ値付ワ着知ソルキ日医ず集新エウカケ投国チ生目ゃ棋運ぐのか寄募オチ性注経どドんて止代わくかな端期幕はかク。
|
||||
)");
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
std::basic_string_view<CharT> emoji_text() {
|
||||
return SV(
|
||||
R"(
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
|
||||
\U0001F636\u200D\U0001F32B\uFE0F
|
||||
|
||||
\U0001F44B\U0001F3FB\U0001F44B\U0001F3FC\U0001F44B\U0001F3FD\U0001F44B\U0001F3FE\U0001F44B\U0001F3FF
|
||||
|
||||
\U0001F468\u200D\U0001F469\u200D\U0001F467\u200D\U0001F466\U0001F1E8\U0001F1E6
|
||||
|
||||
\U0001F984
|
||||
|
||||
)");
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void BM_text(benchmark::State& state, std::basic_string_view<CharT> input) {
|
||||
CharT buffer[5'000];
|
||||
|
||||
if constexpr (std::same_as<CharT, char>) {
|
||||
// Make sure the output buffer is large enough.
|
||||
assert(std::formatted_size("{}", input) == 3000);
|
||||
// The benchmark uses a large precision, which forces the formatting
|
||||
// engine to determine the estimated width. (There's no direct way to call
|
||||
// this function in portable code.)
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(std::format_to(buffer, "{:.10000}", input));
|
||||
} else {
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(std::format_to(buffer, L"{:.10000}", input));
|
||||
}
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void BM_ascii_text(benchmark::State& state) {
|
||||
BM_text(state, ascii_text<CharT>());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void BM_unicode_text(benchmark::State& state) {
|
||||
BM_text(state, unicode_text<CharT>());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void BM_cyrillic_text(benchmark::State& state) {
|
||||
BM_text(state, cyrillic_text<CharT>());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void BM_japanese_text(benchmark::State& state) {
|
||||
BM_text(state, japanese_text<CharT>());
|
||||
}
|
||||
|
||||
template <class CharT>
|
||||
void BM_emoji_text(benchmark::State& state) {
|
||||
BM_text(state, emoji_text<CharT>());
|
||||
}
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_ascii_text, char);
|
||||
BENCHMARK_TEMPLATE(BM_unicode_text, char);
|
||||
BENCHMARK_TEMPLATE(BM_cyrillic_text, char);
|
||||
BENCHMARK_TEMPLATE(BM_japanese_text, char);
|
||||
BENCHMARK_TEMPLATE(BM_emoji_text, char);
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_ascii_text, wchar_t);
|
||||
BENCHMARK_TEMPLATE(BM_unicode_text, wchar_t);
|
||||
BENCHMARK_TEMPLATE(BM_cyrillic_text, wchar_t);
|
||||
BENCHMARK_TEMPLATE(BM_japanese_text, wchar_t);
|
||||
BENCHMARK_TEMPLATE(BM_emoji_text, wchar_t);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
||||
#else
|
||||
int main(int, char**) { return 0; }
|
||||
#endif
|
@ -1,628 +0,0 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <new>
|
||||
#include <vector>
|
||||
|
||||
#include "CartesianBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
constexpr std::size_t MAX_STRING_LEN = 8 << 14;
|
||||
|
||||
// Benchmark when there is no match.
|
||||
static void BM_StringFindNoMatch(benchmark::State &state) {
|
||||
std::string s1(state.range(0), '-');
|
||||
std::string s2(8, '*');
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(s1.find(s2));
|
||||
}
|
||||
BENCHMARK(BM_StringFindNoMatch)->Range(10, MAX_STRING_LEN);
|
||||
|
||||
// Benchmark when the string matches first time.
|
||||
static void BM_StringFindAllMatch(benchmark::State &state) {
|
||||
std::string s1(MAX_STRING_LEN, '-');
|
||||
std::string s2(state.range(0), '-');
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(s1.find(s2));
|
||||
}
|
||||
BENCHMARK(BM_StringFindAllMatch)->Range(1, MAX_STRING_LEN);
|
||||
|
||||
// Benchmark when the string matches somewhere in the end.
|
||||
static void BM_StringFindMatch1(benchmark::State &state) {
|
||||
std::string s1(MAX_STRING_LEN / 2, '*');
|
||||
s1 += std::string(state.range(0), '-');
|
||||
std::string s2(state.range(0), '-');
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(s1.find(s2));
|
||||
}
|
||||
BENCHMARK(BM_StringFindMatch1)->Range(1, MAX_STRING_LEN / 4);
|
||||
|
||||
// Benchmark when the string matches somewhere from middle to the end.
|
||||
static void BM_StringFindMatch2(benchmark::State &state) {
|
||||
std::string s1(MAX_STRING_LEN / 2, '*');
|
||||
s1 += std::string(state.range(0), '-');
|
||||
s1 += std::string(state.range(0), '*');
|
||||
std::string s2(state.range(0), '-');
|
||||
for (auto _ : state)
|
||||
benchmark::DoNotOptimize(s1.find(s2));
|
||||
}
|
||||
BENCHMARK(BM_StringFindMatch2)->Range(1, MAX_STRING_LEN / 4);
|
||||
|
||||
static void BM_StringCtorDefault(benchmark::State &state) {
|
||||
for (auto _ : state) {
|
||||
std::string Default;
|
||||
benchmark::DoNotOptimize(Default);
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_StringCtorDefault);
|
||||
|
||||
enum class Length { Empty, Small, Large, Huge };
|
||||
struct AllLengths : EnumValuesAsTuple<AllLengths, Length, 4> {
|
||||
static constexpr const char* Names[] = {"Empty", "Small", "Large", "Huge"};
|
||||
};
|
||||
|
||||
enum class Opacity { Opaque, Transparent };
|
||||
struct AllOpacity : EnumValuesAsTuple<AllOpacity, Opacity, 2> {
|
||||
static constexpr const char* Names[] = {"Opaque", "Transparent"};
|
||||
};
|
||||
|
||||
enum class DiffType { Control, ChangeFirst, ChangeMiddle, ChangeLast };
|
||||
struct AllDiffTypes : EnumValuesAsTuple<AllDiffTypes, DiffType, 4> {
|
||||
static constexpr const char* Names[] = {"Control", "ChangeFirst",
|
||||
"ChangeMiddle", "ChangeLast"};
|
||||
};
|
||||
|
||||
static constexpr char SmallStringLiteral[] = "012345678";
|
||||
|
||||
TEST_ALWAYS_INLINE const char* getSmallString(DiffType D) {
|
||||
switch (D) {
|
||||
case DiffType::Control:
|
||||
return SmallStringLiteral;
|
||||
case DiffType::ChangeFirst:
|
||||
return "-12345678";
|
||||
case DiffType::ChangeMiddle:
|
||||
return "0123-5678";
|
||||
case DiffType::ChangeLast:
|
||||
return "01234567-";
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr char LargeStringLiteral[] =
|
||||
"012345678901234567890123456789012345678901234567890123456789012";
|
||||
|
||||
TEST_ALWAYS_INLINE const char* getLargeString(DiffType D) {
|
||||
#define LARGE_STRING_FIRST "123456789012345678901234567890"
|
||||
#define LARGE_STRING_SECOND "234567890123456789012345678901"
|
||||
switch (D) {
|
||||
case DiffType::Control:
|
||||
return "0" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "2";
|
||||
case DiffType::ChangeFirst:
|
||||
return "-" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "2";
|
||||
case DiffType::ChangeMiddle:
|
||||
return "0" LARGE_STRING_FIRST "-" LARGE_STRING_SECOND "2";
|
||||
case DiffType::ChangeLast:
|
||||
return "0" LARGE_STRING_FIRST "1" LARGE_STRING_SECOND "-";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ALWAYS_INLINE const char* getHugeString(DiffType D) {
|
||||
#define HUGE_STRING0 "0123456789"
|
||||
#define HUGE_STRING1 HUGE_STRING0 HUGE_STRING0 HUGE_STRING0 HUGE_STRING0
|
||||
#define HUGE_STRING2 HUGE_STRING1 HUGE_STRING1 HUGE_STRING1 HUGE_STRING1
|
||||
#define HUGE_STRING3 HUGE_STRING2 HUGE_STRING2 HUGE_STRING2 HUGE_STRING2
|
||||
#define HUGE_STRING4 HUGE_STRING3 HUGE_STRING3 HUGE_STRING3 HUGE_STRING3
|
||||
switch (D) {
|
||||
case DiffType::Control:
|
||||
return "0123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "0123456789";
|
||||
case DiffType::ChangeFirst:
|
||||
return "-123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "0123456789";
|
||||
case DiffType::ChangeMiddle:
|
||||
return "0123456789" HUGE_STRING4 "01234-6789" HUGE_STRING4 "0123456789";
|
||||
case DiffType::ChangeLast:
|
||||
return "0123456789" HUGE_STRING4 "0123456789" HUGE_STRING4 "012345678-";
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ALWAYS_INLINE const char* getString(Length L,
|
||||
DiffType D = DiffType::Control) {
|
||||
switch (L) {
|
||||
case Length::Empty:
|
||||
return "";
|
||||
case Length::Small:
|
||||
return getSmallString(D);
|
||||
case Length::Large:
|
||||
return getLargeString(D);
|
||||
case Length::Huge:
|
||||
return getHugeString(D);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_ALWAYS_INLINE std::string makeString(Length L,
|
||||
DiffType D = DiffType::Control,
|
||||
Opacity O = Opacity::Transparent) {
|
||||
switch (L) {
|
||||
case Length::Empty:
|
||||
return maybeOpaque("", O == Opacity::Opaque);
|
||||
case Length::Small:
|
||||
return maybeOpaque(getSmallString(D), O == Opacity::Opaque);
|
||||
case Length::Large:
|
||||
return maybeOpaque(getLargeString(D), O == Opacity::Opaque);
|
||||
case Length::Huge:
|
||||
return maybeOpaque(getHugeString(D), O == Opacity::Opaque);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Length, class Opaque>
|
||||
struct StringConstructDestroyCStr {
|
||||
static void run(benchmark::State& state) {
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(
|
||||
makeString(Length(), DiffType::Control, Opaque()));
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringConstructDestroyCStr" + Length::name() + Opaque::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Length, bool MeasureCopy, bool MeasureDestroy>
|
||||
static void StringCopyAndDestroy(benchmark::State& state) {
|
||||
static constexpr size_t NumStrings = 1024;
|
||||
auto Orig = makeString(Length());
|
||||
std::aligned_storage<sizeof(std::string)>::type Storage[NumStrings];
|
||||
|
||||
while (state.KeepRunningBatch(NumStrings)) {
|
||||
if (!MeasureCopy)
|
||||
state.PauseTiming();
|
||||
for (size_t I = 0; I < NumStrings; ++I) {
|
||||
::new (static_cast<void*>(Storage + I)) std::string(Orig);
|
||||
}
|
||||
if (!MeasureCopy)
|
||||
state.ResumeTiming();
|
||||
if (!MeasureDestroy)
|
||||
state.PauseTiming();
|
||||
for (size_t I = 0; I < NumStrings; ++I) {
|
||||
using S = std::string;
|
||||
reinterpret_cast<S*>(Storage + I)->~S();
|
||||
}
|
||||
if (!MeasureDestroy)
|
||||
state.ResumeTiming();
|
||||
}
|
||||
}
|
||||
|
||||
template <class Length>
|
||||
struct StringCopy {
|
||||
static void run(benchmark::State& state) {
|
||||
StringCopyAndDestroy<Length, true, false>(state);
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_StringCopy" + Length::name(); }
|
||||
};
|
||||
|
||||
template <class Length>
|
||||
struct StringDestroy {
|
||||
static void run(benchmark::State& state) {
|
||||
StringCopyAndDestroy<Length, false, true>(state);
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_StringDestroy" + Length::name(); }
|
||||
};
|
||||
|
||||
template <class Length>
|
||||
struct StringMove {
|
||||
static void run(benchmark::State& state) {
|
||||
// Keep two object locations and move construct back and forth.
|
||||
std::aligned_storage<sizeof(std::string), alignof(std::string)>::type Storage[2];
|
||||
using S = std::string;
|
||||
size_t I = 0;
|
||||
S *newS = new (static_cast<void*>(Storage)) std::string(makeString(Length()));
|
||||
for (auto _ : state) {
|
||||
// Switch locations.
|
||||
I ^= 1;
|
||||
benchmark::DoNotOptimize(Storage);
|
||||
// Move construct into the new location,
|
||||
S *tmpS = new (static_cast<void*>(Storage + I)) S(std::move(*newS));
|
||||
// then destroy the old one.
|
||||
newS->~S();
|
||||
newS = tmpS;
|
||||
}
|
||||
newS->~S();
|
||||
}
|
||||
|
||||
static std::string name() { return "BM_StringMove" + Length::name(); }
|
||||
};
|
||||
|
||||
template <class Length, class Opaque>
|
||||
struct StringResizeDefaultInit {
|
||||
static void run(benchmark::State& state) {
|
||||
constexpr bool opaque = Opaque{} == Opacity::Opaque;
|
||||
constexpr int kNumStrings = 4 << 10;
|
||||
size_t length = makeString(Length()).size();
|
||||
std::string strings[kNumStrings];
|
||||
while (state.KeepRunningBatch(kNumStrings)) {
|
||||
state.PauseTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
std::string().swap(strings[i]);
|
||||
}
|
||||
benchmark::DoNotOptimize(strings);
|
||||
state.ResumeTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
strings[i].__resize_default_init(maybeOpaque(length, opaque));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringResizeDefaultInit" + Length::name() + Opaque::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Length, class Opaque>
|
||||
struct StringAssignStr {
|
||||
static void run(benchmark::State& state) {
|
||||
constexpr bool opaque = Opaque{} == Opacity::Opaque;
|
||||
constexpr int kNumStrings = 4 << 10;
|
||||
std::string src = makeString(Length());
|
||||
std::string strings[kNumStrings];
|
||||
while (state.KeepRunningBatch(kNumStrings)) {
|
||||
state.PauseTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
std::string().swap(strings[i]);
|
||||
}
|
||||
benchmark::DoNotOptimize(strings);
|
||||
state.ResumeTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
strings[i] = *maybeOpaque(&src, opaque);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringAssignStr" + Length::name() + Opaque::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Length, class Opaque>
|
||||
struct StringAssignAsciiz {
|
||||
static void run(benchmark::State& state) {
|
||||
constexpr bool opaque = Opaque{} == Opacity::Opaque;
|
||||
constexpr int kNumStrings = 4 << 10;
|
||||
std::string strings[kNumStrings];
|
||||
while (state.KeepRunningBatch(kNumStrings)) {
|
||||
state.PauseTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
std::string().swap(strings[i]);
|
||||
}
|
||||
benchmark::DoNotOptimize(strings);
|
||||
state.ResumeTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
strings[i] = maybeOpaque(getString(Length()), opaque);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringAssignAsciiz" + Length::name() + Opaque::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Length, class Opaque>
|
||||
struct StringEraseToEnd {
|
||||
static void run(benchmark::State& state) {
|
||||
constexpr bool opaque = Opaque{} == Opacity::Opaque;
|
||||
constexpr int kNumStrings = 4 << 10;
|
||||
std::string strings[kNumStrings];
|
||||
const int mid = makeString(Length()).size() / 2;
|
||||
while (state.KeepRunningBatch(kNumStrings)) {
|
||||
state.PauseTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
strings[i] = makeString(Length());
|
||||
}
|
||||
benchmark::DoNotOptimize(strings);
|
||||
state.ResumeTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
strings[i].erase(maybeOpaque(mid, opaque),
|
||||
maybeOpaque(std::string::npos, opaque));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringEraseToEnd" + Length::name() + Opaque::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Length, class Opaque>
|
||||
struct StringEraseWithMove {
|
||||
static void run(benchmark::State& state) {
|
||||
constexpr bool opaque = Opaque{} == Opacity::Opaque;
|
||||
constexpr int kNumStrings = 4 << 10;
|
||||
std::string strings[kNumStrings];
|
||||
const int n = makeString(Length()).size() / 2;
|
||||
const int pos = n / 2;
|
||||
while (state.KeepRunningBatch(kNumStrings)) {
|
||||
state.PauseTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
strings[i] = makeString(Length());
|
||||
}
|
||||
benchmark::DoNotOptimize(strings);
|
||||
state.ResumeTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
strings[i].erase(maybeOpaque(pos, opaque), maybeOpaque(n, opaque));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringEraseWithMove" + Length::name() + Opaque::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Opaque>
|
||||
struct StringAssignAsciizMix {
|
||||
static void run(benchmark::State& state) {
|
||||
constexpr auto O = Opaque{};
|
||||
constexpr auto D = DiffType::Control;
|
||||
constexpr int kNumStrings = 4 << 10;
|
||||
std::string strings[kNumStrings];
|
||||
while (state.KeepRunningBatch(kNumStrings)) {
|
||||
state.PauseTiming();
|
||||
for (int i = 0; i < kNumStrings; ++i) {
|
||||
std::string().swap(strings[i]);
|
||||
}
|
||||
benchmark::DoNotOptimize(strings);
|
||||
state.ResumeTiming();
|
||||
for (int i = 0; i < kNumStrings - 7; i += 8) {
|
||||
strings[i + 0] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
|
||||
strings[i + 1] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
|
||||
strings[i + 2] = maybeOpaque(getLargeString(D), O == Opacity::Opaque);
|
||||
strings[i + 3] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
|
||||
strings[i + 4] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
|
||||
strings[i + 5] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
|
||||
strings[i + 6] = maybeOpaque(getLargeString(D), O == Opacity::Opaque);
|
||||
strings[i + 7] = maybeOpaque(getSmallString(D), O == Opacity::Opaque);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringAssignAsciizMix" + Opaque::name();
|
||||
}
|
||||
};
|
||||
|
||||
enum class Relation { Eq, Less, Compare };
|
||||
struct AllRelations : EnumValuesAsTuple<AllRelations, Relation, 3> {
|
||||
static constexpr const char* Names[] = {"Eq", "Less", "Compare"};
|
||||
};
|
||||
|
||||
template <class Rel, class LHLength, class RHLength, class DiffType>
|
||||
struct StringRelational {
|
||||
static void run(benchmark::State& state) {
|
||||
auto Lhs = makeString(RHLength());
|
||||
auto Rhs = makeString(LHLength(), DiffType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(Lhs);
|
||||
benchmark::DoNotOptimize(Rhs);
|
||||
switch (Rel()) {
|
||||
case Relation::Eq:
|
||||
benchmark::DoNotOptimize(Lhs == Rhs);
|
||||
break;
|
||||
case Relation::Less:
|
||||
benchmark::DoNotOptimize(Lhs < Rhs);
|
||||
break;
|
||||
case Relation::Compare:
|
||||
benchmark::DoNotOptimize(Lhs.compare(Rhs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() {
|
||||
// Eq is commutative, so skip half the matrix.
|
||||
if (Rel() == Relation::Eq && LHLength() > RHLength())
|
||||
return true;
|
||||
// We only care about control when the lengths differ.
|
||||
if (LHLength() != RHLength() && DiffType() != ::DiffType::Control)
|
||||
return true;
|
||||
// For empty, only control matters.
|
||||
if (LHLength() == Length::Empty && DiffType() != ::DiffType::Control)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringRelational" + Rel::name() + LHLength::name() +
|
||||
RHLength::name() + DiffType::name();
|
||||
}
|
||||
};
|
||||
|
||||
template <class Rel, class LHLength, class RHLength, class DiffType>
|
||||
struct StringRelationalLiteral {
|
||||
static void run(benchmark::State& state) {
|
||||
auto Lhs = makeString(LHLength(), DiffType());
|
||||
for (auto _ : state) {
|
||||
benchmark::DoNotOptimize(Lhs);
|
||||
constexpr const char* Literal = RHLength::value == Length::Empty
|
||||
? ""
|
||||
: RHLength::value == Length::Small
|
||||
? SmallStringLiteral
|
||||
: LargeStringLiteral;
|
||||
switch (Rel()) {
|
||||
case Relation::Eq:
|
||||
benchmark::DoNotOptimize(Lhs == Literal);
|
||||
break;
|
||||
case Relation::Less:
|
||||
benchmark::DoNotOptimize(Lhs < Literal);
|
||||
break;
|
||||
case Relation::Compare:
|
||||
benchmark::DoNotOptimize(Lhs.compare(Literal));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() {
|
||||
// Doesn't matter how they differ if they have different size.
|
||||
if (LHLength() != RHLength() && DiffType() != ::DiffType::Control)
|
||||
return true;
|
||||
// We don't need huge. Doensn't give anything different than Large.
|
||||
if (LHLength() == Length::Huge || RHLength() == Length::Huge)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string name() {
|
||||
return "BM_StringRelationalLiteral" + Rel::name() + LHLength::name() +
|
||||
RHLength::name() + DiffType::name();
|
||||
}
|
||||
};
|
||||
|
||||
enum class Depth { Shallow, Deep };
|
||||
struct AllDepths : EnumValuesAsTuple<AllDepths, Depth, 2> {
|
||||
static constexpr const char* Names[] = {"Shallow", "Deep"};
|
||||
};
|
||||
|
||||
enum class Temperature { Hot, Cold };
|
||||
struct AllTemperatures : EnumValuesAsTuple<AllTemperatures, Temperature, 2> {
|
||||
static constexpr const char* Names[] = {"Hot", "Cold"};
|
||||
};
|
||||
|
||||
template <class Temperature, class Depth, class Length>
|
||||
struct StringRead {
|
||||
void run(benchmark::State& state) const {
|
||||
static constexpr size_t NumStrings =
|
||||
Temperature() == ::Temperature::Hot
|
||||
? 1 << 10
|
||||
: /* Enough strings to overflow the cache */ 1 << 20;
|
||||
static_assert((NumStrings & (NumStrings - 1)) == 0,
|
||||
"NumStrings should be a power of two to reduce overhead.");
|
||||
|
||||
std::vector<std::string> Values(NumStrings, makeString(Length()));
|
||||
size_t I = 0;
|
||||
for (auto _ : state) {
|
||||
// Jump long enough to defeat cache locality, and use a value that is
|
||||
// coprime with NumStrings to ensure we visit every element.
|
||||
I = (I + 17) % NumStrings;
|
||||
const auto& V = Values[I];
|
||||
|
||||
// Read everything first. Escaping data() through DoNotOptimize might
|
||||
// cause the compiler to have to recalculate information about `V` due to
|
||||
// aliasing.
|
||||
const char* const Data = V.data();
|
||||
const size_t Size = V.size();
|
||||
benchmark::DoNotOptimize(Data);
|
||||
benchmark::DoNotOptimize(Size);
|
||||
if (Depth() == ::Depth::Deep) {
|
||||
// Read into the payload. This mainly shows the benefit of SSO when the
|
||||
// data is cold.
|
||||
benchmark::DoNotOptimize(*Data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool skip() {
|
||||
// Huge does not give us anything that Large doesn't have. Skip it.
|
||||
if (Length() == ::Length::Huge) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string name() const {
|
||||
return "BM_StringRead" + Temperature::name() + Depth::name() +
|
||||
Length::name();
|
||||
}
|
||||
};
|
||||
|
||||
void sanityCheckGeneratedStrings() {
|
||||
for (auto Lhs : {Length::Empty, Length::Small, Length::Large, Length::Huge}) {
|
||||
const auto LhsString = makeString(Lhs);
|
||||
for (auto Rhs :
|
||||
{Length::Empty, Length::Small, Length::Large, Length::Huge}) {
|
||||
if (Lhs > Rhs)
|
||||
continue;
|
||||
const auto RhsString = makeString(Rhs);
|
||||
|
||||
// The smaller one must be a prefix of the larger one.
|
||||
if (RhsString.find(LhsString) != 0) {
|
||||
fprintf(stderr, "Invalid autogenerated strings for sizes (%d,%d).\n",
|
||||
static_cast<int>(Lhs), static_cast<int>(Rhs));
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Verify the autogenerated diffs
|
||||
for (auto L : {Length::Small, Length::Large, Length::Huge}) {
|
||||
const auto Control = makeString(L);
|
||||
const auto Verify = [&](std::string Exp, size_t Pos) {
|
||||
// Only change on the Pos char.
|
||||
if (Control[Pos] != Exp[Pos]) {
|
||||
Exp[Pos] = Control[Pos];
|
||||
if (Control == Exp)
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "Invalid autogenerated diff with size %d\n",
|
||||
static_cast<int>(L));
|
||||
std::abort();
|
||||
};
|
||||
Verify(makeString(L, DiffType::ChangeFirst), 0);
|
||||
Verify(makeString(L, DiffType::ChangeMiddle), Control.size() / 2);
|
||||
Verify(makeString(L, DiffType::ChangeLast), Control.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Some small codegen thunks to easily see generated code.
|
||||
bool StringEqString(const std::string& a, const std::string& b) {
|
||||
return a == b;
|
||||
}
|
||||
bool StringEqCStr(const std::string& a, const char* b) { return a == b; }
|
||||
bool CStrEqString(const char* a, const std::string& b) { return a == b; }
|
||||
bool StringEqCStrLiteralEmpty(const std::string& a) {
|
||||
return a == "";
|
||||
}
|
||||
bool StringEqCStrLiteralSmall(const std::string& a) {
|
||||
return a == SmallStringLiteral;
|
||||
}
|
||||
bool StringEqCStrLiteralLarge(const std::string& a) {
|
||||
return a == LargeStringLiteral;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
sanityCheckGeneratedStrings();
|
||||
|
||||
makeCartesianProductBenchmark<StringConstructDestroyCStr, AllLengths,
|
||||
AllOpacity>();
|
||||
|
||||
makeCartesianProductBenchmark<StringAssignStr, AllLengths, AllOpacity>();
|
||||
makeCartesianProductBenchmark<StringAssignAsciiz, AllLengths, AllOpacity>();
|
||||
makeCartesianProductBenchmark<StringAssignAsciizMix, AllOpacity>();
|
||||
|
||||
makeCartesianProductBenchmark<StringCopy, AllLengths>();
|
||||
makeCartesianProductBenchmark<StringMove, AllLengths>();
|
||||
makeCartesianProductBenchmark<StringDestroy, AllLengths>();
|
||||
makeCartesianProductBenchmark<StringResizeDefaultInit, AllLengths,
|
||||
AllOpacity>();
|
||||
makeCartesianProductBenchmark<StringEraseToEnd, AllLengths, AllOpacity>();
|
||||
makeCartesianProductBenchmark<StringEraseWithMove, AllLengths, AllOpacity>();
|
||||
makeCartesianProductBenchmark<StringRelational, AllRelations, AllLengths,
|
||||
AllLengths, AllDiffTypes>();
|
||||
makeCartesianProductBenchmark<StringRelationalLiteral, AllRelations,
|
||||
AllLengths, AllLengths, AllDiffTypes>();
|
||||
makeCartesianProductBenchmark<StringRead, AllTemperatures, AllDepths,
|
||||
AllLengths>();
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
|
||||
if (argc < 0) {
|
||||
// ODR-use the functions to force them being generated in the binary.
|
||||
auto functions = std::make_tuple(
|
||||
StringEqString, StringEqCStr, CStrEqString, StringEqCStrLiteralEmpty,
|
||||
StringEqCStrLiteralSmall, StringEqCStrLiteralLarge);
|
||||
printf("%p", &functions);
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
TEST_NOINLINE double istream_numbers();
|
||||
|
||||
double istream_numbers() {
|
||||
const char *a[] = {
|
||||
"-6 69 -71 2.4882e-02 -100 101 -2.00005 5000000 -50000000",
|
||||
"-25 71 7 -9.3262e+01 -100 101 -2.00005 5000000 -50000000",
|
||||
"-14 53 46 -6.7026e-02 -100 101 -2.00005 5000000 -50000000"
|
||||
};
|
||||
|
||||
int a1, a2, a3, a4, a5, a6, a7;
|
||||
double f1 = 0.0, f2 = 0.0, q = 0.0;
|
||||
for (int i=0; i < 3; i++) {
|
||||
std::istringstream s(a[i]);
|
||||
s >> a1
|
||||
>> a2
|
||||
>> a3
|
||||
>> f1
|
||||
>> a4
|
||||
>> a5
|
||||
>> f2
|
||||
>> a6
|
||||
>> a7;
|
||||
q += (a1 + a2 + a3 + a4 + a5 + a6 + a7 + f1 + f2)/1000000;
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
static void BM_Istream_numbers(benchmark::State &state) {
|
||||
double i = 0;
|
||||
while (state.KeepRunning())
|
||||
benchmark::DoNotOptimize(i += istream_numbers());
|
||||
}
|
||||
|
||||
BENCHMARK(BM_Istream_numbers)->RangeMultiplier(2)->Range(1024, 4096);
|
||||
BENCHMARK_MAIN();
|
@ -1,58 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <array>
|
||||
#include <charconv>
|
||||
#include <random>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
static const std::array<unsigned, 1000> input = [] {
|
||||
std::mt19937 generator;
|
||||
std::uniform_int_distribution<unsigned> distribution(0, std::numeric_limits<unsigned>::max());
|
||||
std::array<unsigned, 1000> result;
|
||||
std::generate_n(result.begin(), result.size(), [&] { return distribution(generator); });
|
||||
return result;
|
||||
}();
|
||||
|
||||
static void BM_to_chars_good(benchmark::State& state) {
|
||||
char buffer[128];
|
||||
int base = state.range(0);
|
||||
while (state.KeepRunningBatch(input.size()))
|
||||
for (auto value : input)
|
||||
benchmark::DoNotOptimize(std::to_chars(buffer, &buffer[128], value, base));
|
||||
}
|
||||
BENCHMARK(BM_to_chars_good)->DenseRange(2, 36, 1);
|
||||
|
||||
static void BM_to_chars_bad(benchmark::State& state) {
|
||||
char buffer[128];
|
||||
int base = state.range(0);
|
||||
struct sample {
|
||||
unsigned size;
|
||||
unsigned value;
|
||||
};
|
||||
std::array<sample, 1000> data;
|
||||
// Assume the failure occurs, on average, halfway during the conversion.
|
||||
std::transform(input.begin(), input.end(), data.begin(), [&](unsigned value) {
|
||||
std::to_chars_result result = std::to_chars(buffer, &buffer[128], value, base);
|
||||
return sample{unsigned((result.ptr - buffer) / 2), value};
|
||||
});
|
||||
|
||||
while (state.KeepRunningBatch(data.size()))
|
||||
for (auto element : data)
|
||||
benchmark::DoNotOptimize(std::to_chars(buffer, &buffer[element.size], element.value, base));
|
||||
}
|
||||
BENCHMARK(BM_to_chars_bad)->DenseRange(2, 36, 1);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
benchmark::Initialize(&argc, argv);
|
||||
if (benchmark::ReportUnrecognizedArguments(argc, argv))
|
||||
return 1;
|
||||
|
||||
benchmark::RunSpecifiedBenchmarks();
|
||||
}
|
@ -1,342 +0,0 @@
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "ContainerBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
using namespace ContainerBenchmarks;
|
||||
|
||||
constexpr std::size_t TestNumInputs = 1024;
|
||||
|
||||
template <class _Size>
|
||||
inline TEST_ALWAYS_INLINE
|
||||
_Size loadword(const void* __p) {
|
||||
_Size __r;
|
||||
std::memcpy(&__r, __p, sizeof(__r));
|
||||
return __r;
|
||||
}
|
||||
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t rotate_by_at_least_1(std::size_t __val, int __shift) {
|
||||
return (__val >> __shift) | (__val << (64 - __shift));
|
||||
}
|
||||
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t hash_len_16(std::size_t __u, std::size_t __v) {
|
||||
const std::size_t __mul = 0x9ddfea08eb382d69ULL;
|
||||
std::size_t __a = (__u ^ __v) * __mul;
|
||||
__a ^= (__a >> 47);
|
||||
std::size_t __b = (__v ^ __a) * __mul;
|
||||
__b ^= (__b >> 47);
|
||||
__b *= __mul;
|
||||
return __b;
|
||||
}
|
||||
|
||||
|
||||
template <std::size_t _Len>
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t hash_len_0_to_8(const char* __s) {
|
||||
static_assert(_Len == 4 || _Len == 8, "");
|
||||
const uint64_t __a = loadword<uint32_t>(__s);
|
||||
const uint64_t __b = loadword<uint32_t>(__s + _Len - 4);
|
||||
return hash_len_16(_Len + (__a << 3), __b);
|
||||
}
|
||||
|
||||
struct UInt32Hash {
|
||||
UInt32Hash() = default;
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(uint32_t data) const {
|
||||
return hash_len_0_to_8<4>(reinterpret_cast<const char*>(&data));
|
||||
}
|
||||
};
|
||||
|
||||
struct UInt64Hash {
|
||||
UInt64Hash() = default;
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(uint64_t data) const {
|
||||
return hash_len_0_to_8<8>(reinterpret_cast<const char*>(&data));
|
||||
}
|
||||
};
|
||||
|
||||
struct UInt128Hash {
|
||||
UInt128Hash() = default;
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(__uint128_t data) const {
|
||||
const __uint128_t __mask = static_cast<std::size_t>(-1);
|
||||
const std::size_t __a = (std::size_t)(data & __mask);
|
||||
const std::size_t __b = (std::size_t)((data & (__mask << 64)) >> 64);
|
||||
return hash_len_16(__a, rotate_by_at_least_1(__b + 16, 16)) ^ __b;
|
||||
}
|
||||
};
|
||||
|
||||
struct UInt32Hash2 {
|
||||
UInt32Hash2() = default;
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(uint32_t data) const {
|
||||
const uint32_t __m = 0x5bd1e995;
|
||||
const uint32_t __r = 24;
|
||||
uint32_t __h = 4;
|
||||
uint32_t __k = data;
|
||||
__k *= __m;
|
||||
__k ^= __k >> __r;
|
||||
__k *= __m;
|
||||
__h *= __m;
|
||||
__h ^= __k;
|
||||
__h ^= __h >> 13;
|
||||
__h *= __m;
|
||||
__h ^= __h >> 15;
|
||||
return __h;
|
||||
}
|
||||
};
|
||||
|
||||
struct UInt64Hash2 {
|
||||
UInt64Hash2() = default;
|
||||
inline TEST_ALWAYS_INLINE
|
||||
std::size_t operator()(uint64_t data) const {
|
||||
return hash_len_0_to_8<8>(reinterpret_cast<const char*>(&data));
|
||||
}
|
||||
};
|
||||
|
||||
// The sole purpose of this comparator is to be used in BM_Rehash, where
|
||||
// we need something slow enough to be easily noticable in benchmark results.
|
||||
// The default implementation of operator== for strings seems to be a little
|
||||
// too fast for that specific benchmark to reliably show a noticeable
|
||||
// improvement, but unoptimized bytewise comparison fits just right.
|
||||
// Early return is there just for convenience, since we only compare strings
|
||||
// of equal length in BM_Rehash.
|
||||
struct SlowStringEq {
|
||||
SlowStringEq() = default;
|
||||
inline TEST_ALWAYS_INLINE
|
||||
bool operator()(const std::string& lhs, const std::string& rhs) const {
|
||||
if (lhs.size() != rhs.size()) return false;
|
||||
|
||||
bool eq = true;
|
||||
for (size_t i = 0; i < lhs.size(); ++i) {
|
||||
eq &= lhs[i] == rhs[i];
|
||||
}
|
||||
return eq;
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// BM_Hash
|
||||
// ---------------------------------------------------------------------------//
|
||||
|
||||
template <class HashFn, class GenInputs>
|
||||
void BM_Hash(benchmark::State& st, HashFn fn, GenInputs gen) {
|
||||
auto in = gen(st.range(0));
|
||||
const auto end = in.data() + in.size();
|
||||
std::size_t last_hash = 0;
|
||||
benchmark::DoNotOptimize(&last_hash);
|
||||
while (st.KeepRunning()) {
|
||||
for (auto it = in.data(); it != end; ++it) {
|
||||
benchmark::DoNotOptimize(last_hash += fn(*it));
|
||||
}
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Hash,
|
||||
uint32_random_std_hash,
|
||||
std::hash<uint32_t>{},
|
||||
getRandomIntegerInputs<uint32_t>) -> Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Hash,
|
||||
uint32_random_custom_hash,
|
||||
UInt32Hash{},
|
||||
getRandomIntegerInputs<uint32_t>) -> Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Hash,
|
||||
uint32_top_std_hash,
|
||||
std::hash<uint32_t>{},
|
||||
getSortedTopBitsIntegerInputs<uint32_t>) -> Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Hash,
|
||||
uint32_top_custom_hash,
|
||||
UInt32Hash{},
|
||||
getSortedTopBitsIntegerInputs<uint32_t>) -> Arg(TestNumInputs);
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// BM_InsertValue
|
||||
// ---------------------------------------------------------------------------//
|
||||
|
||||
|
||||
// Sorted Ascending //
|
||||
BENCHMARK_CAPTURE(BM_InsertValue,
|
||||
unordered_set_uint32,
|
||||
std::unordered_set<uint32_t>{},
|
||||
getRandomIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_InsertValue,
|
||||
unordered_set_uint32_sorted,
|
||||
std::unordered_set<uint32_t>{},
|
||||
getSortedIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
|
||||
// Top Bytes //
|
||||
BENCHMARK_CAPTURE(BM_InsertValue,
|
||||
unordered_set_top_bits_uint32,
|
||||
std::unordered_set<uint32_t>{},
|
||||
getSortedTopBitsIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_InsertValueRehash,
|
||||
unordered_set_top_bits_uint32,
|
||||
std::unordered_set<uint32_t, UInt32Hash>{},
|
||||
getSortedTopBitsIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
|
||||
// String //
|
||||
BENCHMARK_CAPTURE(BM_InsertValue,
|
||||
unordered_set_string,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_InsertValueRehash,
|
||||
unordered_set_string,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// BM_Find
|
||||
// ---------------------------------------------------------------------------//
|
||||
|
||||
// Random //
|
||||
BENCHMARK_CAPTURE(BM_Find,
|
||||
unordered_set_random_uint64,
|
||||
std::unordered_set<uint64_t>{},
|
||||
getRandomIntegerInputs<uint64_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_FindRehash,
|
||||
unordered_set_random_uint64,
|
||||
std::unordered_set<uint64_t, UInt64Hash>{},
|
||||
getRandomIntegerInputs<uint64_t>)->Arg(TestNumInputs);
|
||||
|
||||
// Sorted //
|
||||
BENCHMARK_CAPTURE(BM_Find,
|
||||
unordered_set_sorted_uint64,
|
||||
std::unordered_set<uint64_t>{},
|
||||
getSortedIntegerInputs<uint64_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_FindRehash,
|
||||
unordered_set_sorted_uint64,
|
||||
std::unordered_set<uint64_t, UInt64Hash>{},
|
||||
getSortedIntegerInputs<uint64_t>)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
// Sorted //
|
||||
#if 1
|
||||
BENCHMARK_CAPTURE(BM_Find,
|
||||
unordered_set_sorted_uint128,
|
||||
std::unordered_set<__uint128_t, UInt128Hash>{},
|
||||
getSortedTopBitsIntegerInputs<__uint128_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_FindRehash,
|
||||
unordered_set_sorted_uint128,
|
||||
std::unordered_set<__uint128_t, UInt128Hash>{},
|
||||
getSortedTopBitsIntegerInputs<__uint128_t>)->Arg(TestNumInputs);
|
||||
#endif
|
||||
|
||||
// Sorted //
|
||||
BENCHMARK_CAPTURE(BM_Find,
|
||||
unordered_set_sorted_uint32,
|
||||
std::unordered_set<uint32_t>{},
|
||||
getSortedIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_FindRehash,
|
||||
unordered_set_sorted_uint32,
|
||||
std::unordered_set<uint32_t, UInt32Hash2>{},
|
||||
getSortedIntegerInputs<uint32_t>)->Arg(TestNumInputs);
|
||||
|
||||
// Sorted Ascending //
|
||||
BENCHMARK_CAPTURE(BM_Find,
|
||||
unordered_set_sorted_large_uint64,
|
||||
std::unordered_set<uint64_t>{},
|
||||
getSortedLargeIntegerInputs<uint64_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_FindRehash,
|
||||
unordered_set_sorted_large_uint64,
|
||||
std::unordered_set<uint64_t, UInt64Hash>{},
|
||||
getSortedLargeIntegerInputs<uint64_t>)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
// Top Bits //
|
||||
BENCHMARK_CAPTURE(BM_Find,
|
||||
unordered_set_top_bits_uint64,
|
||||
std::unordered_set<uint64_t>{},
|
||||
getSortedTopBitsIntegerInputs<uint64_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_FindRehash,
|
||||
unordered_set_top_bits_uint64,
|
||||
std::unordered_set<uint64_t, UInt64Hash>{},
|
||||
getSortedTopBitsIntegerInputs<uint64_t>)->Arg(TestNumInputs);
|
||||
|
||||
// String //
|
||||
BENCHMARK_CAPTURE(BM_Find,
|
||||
unordered_set_string,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_FindRehash,
|
||||
unordered_set_string,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
//----------------------------------------------------------------------------//
|
||||
// BM_Rehash
|
||||
// ---------------------------------------------------------------------------//
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Rehash,
|
||||
unordered_set_string_arg,
|
||||
std::unordered_set<std::string, std::hash<std::string>, SlowStringEq>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_Rehash,
|
||||
unordered_set_int_arg,
|
||||
std::unordered_set<int>{},
|
||||
getRandomIntegerInputs<int>)->Arg(TestNumInputs);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
BENCHMARK_CAPTURE(BM_InsertDuplicate,
|
||||
unordered_set_int,
|
||||
std::unordered_set<int>{},
|
||||
getRandomIntegerInputs<int>)->Arg(TestNumInputs);
|
||||
BENCHMARK_CAPTURE(BM_InsertDuplicate,
|
||||
unordered_set_string,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_EmplaceDuplicate,
|
||||
unordered_set_int,
|
||||
std::unordered_set<int>{},
|
||||
getRandomIntegerInputs<int>)->Arg(TestNumInputs);
|
||||
BENCHMARK_CAPTURE(BM_EmplaceDuplicate,
|
||||
unordered_set_string,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_InsertDuplicate,
|
||||
unordered_set_int_insert_arg,
|
||||
std::unordered_set<int>{},
|
||||
getRandomIntegerInputs<int>)->Arg(TestNumInputs);
|
||||
BENCHMARK_CAPTURE(BM_InsertDuplicate,
|
||||
unordered_set_string_insert_arg,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_EmplaceDuplicate,
|
||||
unordered_set_int_insert_arg,
|
||||
std::unordered_set<int>{},
|
||||
getRandomIntegerInputs<unsigned>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_EmplaceDuplicate,
|
||||
unordered_set_string_arg,
|
||||
std::unordered_set<std::string>{},
|
||||
getRandomCStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,41 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
static void BM_SharedPtrCreateDestroy(benchmark::State& st) {
|
||||
while (st.KeepRunning()) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SharedPtrCreateDestroy);
|
||||
|
||||
static void BM_SharedPtrIncDecRef(benchmark::State& st) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
while (st.KeepRunning()) {
|
||||
std::shared_ptr<int> sp2(sp);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_SharedPtrIncDecRef);
|
||||
|
||||
static void BM_WeakPtrIncDecRef(benchmark::State& st) {
|
||||
auto sp = std::make_shared<int>(42);
|
||||
benchmark::DoNotOptimize(sp.get());
|
||||
while (st.KeepRunning()) {
|
||||
std::weak_ptr<int> wp(sp);
|
||||
benchmark::ClobberMemory();
|
||||
}
|
||||
}
|
||||
BENCHMARK(BM_WeakPtrIncDecRef);
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,27 +0,0 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "VariantBenchmarks.h"
|
||||
|
||||
using namespace VariantBenchmarks;
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 1);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 2);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 3);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 4);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 5);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 6);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 7);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 8);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 9);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 10);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 20);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 30);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 40);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 50);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 60);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 70);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 80);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 90);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 1, 100);
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,22 +0,0 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "VariantBenchmarks.h"
|
||||
|
||||
using namespace VariantBenchmarks;
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 1);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 2);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 3);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 4);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 5);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 6);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 7);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 8);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 9);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 10);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 20);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 30);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 40);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 2, 50);
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,20 +0,0 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "VariantBenchmarks.h"
|
||||
|
||||
using namespace VariantBenchmarks;
|
||||
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 1);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 2);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 3);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 4);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 5);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 6);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 7);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 8);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 9);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 10);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 15);
|
||||
BENCHMARK_TEMPLATE(BM_Visit, 3, 20);
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,40 +0,0 @@
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "ContainerBenchmarks.h"
|
||||
#include "GenerateInput.h"
|
||||
|
||||
using namespace ContainerBenchmarks;
|
||||
|
||||
constexpr std::size_t TestNumInputs = 1024;
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructSize,
|
||||
vector_byte,
|
||||
std::vector<unsigned char>{})->Arg(5140480);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructSizeValue,
|
||||
vector_byte,
|
||||
std::vector<unsigned char>{}, 0)->Arg(5140480);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
vector_char,
|
||||
std::vector<char>{},
|
||||
getRandomIntegerInputs<char>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
vector_size_t,
|
||||
std::vector<size_t>{},
|
||||
getRandomIntegerInputs<size_t>)->Arg(TestNumInputs);
|
||||
|
||||
BENCHMARK_CAPTURE(BM_ConstructIterIter,
|
||||
vector_string,
|
||||
std::vector<std::string>{},
|
||||
getRandomStringInputs)->Arg(TestNumInputs);
|
||||
|
||||
|
||||
BENCHMARK_MAIN();
|
@ -1,50 +0,0 @@
|
||||
find_program(CODE_COVERAGE_LCOV lcov)
|
||||
if (NOT CODE_COVERAGE_LCOV)
|
||||
message(FATAL_ERROR "Cannot find lcov...")
|
||||
endif()
|
||||
|
||||
find_program(CODE_COVERAGE_LLVM_COV llvm-cov)
|
||||
if (NOT CODE_COVERAGE_LLVM_COV)
|
||||
message(FATAL_ERROR "Cannot find llvm-cov...")
|
||||
endif()
|
||||
|
||||
find_program(CODE_COVERAGE_GENHTML genhtml)
|
||||
if (NOT CODE_COVERAGE_GENHTML)
|
||||
message(FATAL_ERROR "Cannot find genhtml...")
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_FLAGS_COVERAGE "-g -O0 --coverage")
|
||||
|
||||
function(setup_lcov_test_target_coverage target_name output_dir capture_dirs source_dirs)
|
||||
if (NOT DEFINED LIBCXX_BINARY_DIR)
|
||||
message(FATAL_ERROR "Variable must be set")
|
||||
endif()
|
||||
|
||||
set(GCOV_TOOL "${LIBCXX_BINARY_DIR}/llvm-cov-wrapper")
|
||||
file(GENERATE OUTPUT ${GCOV_TOOL}
|
||||
CONTENT "#!/usr/bin/env bash\n${CODE_COVERAGE_LLVM_COV} gcov \"$@\"\n")
|
||||
|
||||
file(MAKE_DIRECTORY ${output_dir})
|
||||
|
||||
set(CAPTURE_DIRS "")
|
||||
foreach(cdir ${capture_dirs})
|
||||
list(APPEND CAPTURE_DIRS "-d;${cdir}")
|
||||
endforeach()
|
||||
|
||||
set(EXTRACT_DIRS "")
|
||||
foreach(sdir ${source_dirs})
|
||||
list(APPEND EXTRACT_DIRS "'${sdir}/*'")
|
||||
endforeach()
|
||||
|
||||
message(STATUS "Capture Directories: ${CAPTURE_DIRS}")
|
||||
message(STATUS "Extract Directories: ${EXTRACT_DIRS}")
|
||||
|
||||
add_custom_target(generate-lib${target_name}-coverage
|
||||
COMMAND chmod +x ${GCOV_TOOL}
|
||||
COMMAND ${CODE_COVERAGE_LCOV} --gcov-tool ${GCOV_TOOL} --capture ${CAPTURE_DIRS} -o test_coverage.info
|
||||
COMMAND ${CODE_COVERAGE_LCOV} --gcov-tool ${GCOV_TOOL} --extract test_coverage.info ${EXTRACT_DIRS} -o test_coverage.info
|
||||
COMMAND ${CODE_COVERAGE_GENHTML} --demangle-cpp test_coverage.info -o test_coverage
|
||||
COMMAND ${CMAKE_COMMAND} -E remove test_coverage.info
|
||||
WORKING_DIRECTORY ${output_dir}
|
||||
COMMENT "Generating coverage results")
|
||||
endfunction()
|
@ -1,182 +0,0 @@
|
||||
#===============================================================================
|
||||
# Define targets for linking against the selected ABI library
|
||||
#
|
||||
# After including this file, the following targets are defined:
|
||||
# - libcxx-abi-headers: An interface target that allows getting access to the
|
||||
# headers of the selected ABI library.
|
||||
# - libcxx-abi-shared: A target representing the selected shared ABI library.
|
||||
# - libcxx-abi-static: A target representing the selected static ABI library.
|
||||
#
|
||||
# Furthermore, some ABI libraries also define the following target:
|
||||
# - libcxx-abi-shared-objects: An object library representing a set of object files
|
||||
# constituting the ABI library, suitable for bundling
|
||||
# into a shared library.
|
||||
# - libcxx-abi-static-objects: An object library representing a set of object files
|
||||
# constituting the ABI library, suitable for bundling
|
||||
# into a static library.
|
||||
#===============================================================================
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# This function copies the provided headers to a private directory and adds that
|
||||
# path to the given INTERFACE target. That target can then be linked against to
|
||||
# get access to those headers (and only those).
|
||||
#
|
||||
# The problem this solves is that when building against a system-provided ABI library,
|
||||
# the ABI headers might live side-by-side with an actual C++ Standard Library
|
||||
# installation. For that reason, we can't just add `-I <path-to-ABI-headers>`,
|
||||
# since we would end up also adding the system-provided C++ Standard Library to
|
||||
# the search path. Instead, what we do is copy just the ABI library headers to
|
||||
# a private directory and add just that path when we build libc++.
|
||||
function(import_private_headers target include_dirs headers)
|
||||
foreach(header ${headers})
|
||||
set(found FALSE)
|
||||
foreach(incpath ${include_dirs})
|
||||
if (EXISTS "${incpath}/${header}")
|
||||
set(found TRUE)
|
||||
message(STATUS "Looking for ${header} in ${incpath} - found")
|
||||
get_filename_component(dstdir ${header} PATH)
|
||||
get_filename_component(header_file ${header} NAME)
|
||||
set(src ${incpath}/${header})
|
||||
set(dst "${LIBCXX_BINARY_DIR}/private-abi-headers/${dstdir}/${header_file}")
|
||||
|
||||
add_custom_command(OUTPUT ${dst}
|
||||
DEPENDS ${src}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "${LIBCXX_BINARY_DIR}/private-abi-headers/${dstdir}"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} ${dst}
|
||||
COMMENT "Copying C++ ABI header ${header}")
|
||||
list(APPEND abilib_headers "${dst}")
|
||||
else()
|
||||
message(STATUS "Looking for ${header} in ${incpath} - not found")
|
||||
endif()
|
||||
endforeach()
|
||||
if (NOT found)
|
||||
message(WARNING "Failed to find ${header} in ${include_dirs}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Work around https://gitlab.kitware.com/cmake/cmake/-/issues/18399
|
||||
add_library(${target}-generate-private-headers OBJECT ${abilib_headers})
|
||||
set_target_properties(${target}-generate-private-headers PROPERTIES LINKER_LANGUAGE CXX)
|
||||
|
||||
target_link_libraries(${target} INTERFACE ${target}-generate-private-headers)
|
||||
target_include_directories(${target} INTERFACE "${LIBCXX_BINARY_DIR}/private-abi-headers")
|
||||
endfunction()
|
||||
|
||||
# This function creates an imported static library named <target>.
|
||||
# It imports a library named <name> searched at the given <path>.
|
||||
function(import_static_library target path name)
|
||||
add_library(${target} STATIC IMPORTED GLOBAL)
|
||||
find_library(file
|
||||
NAMES "${CMAKE_STATIC_LIBRARY_PREFIX}${name}${CMAKE_STATIC_LIBRARY_SUFFIX}"
|
||||
PATHS "${path}"
|
||||
NO_CACHE)
|
||||
set_target_properties(${target} PROPERTIES IMPORTED_LOCATION "${file}")
|
||||
endfunction()
|
||||
|
||||
# This function creates an imported shared (interface) library named <target>
|
||||
# for the given library <name>.
|
||||
function(import_shared_library target name)
|
||||
add_library(${target} INTERFACE IMPORTED GLOBAL)
|
||||
set_target_properties(${target} PROPERTIES IMPORTED_LIBNAME "${name}")
|
||||
endfunction()
|
||||
|
||||
# Link against a system-provided libstdc++
|
||||
if ("${LIBCXX_CXX_ABI}" STREQUAL "libstdc++")
|
||||
add_library(libcxx-abi-headers INTERFACE)
|
||||
import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}"
|
||||
"cxxabi.h;bits/c++config.h;bits/os_defines.h;bits/cpu_defines.h;bits/cxxabi_tweaks.h;bits/cxxabi_forced.h")
|
||||
target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBSTDCXX" "-D__GLIBCXX__")
|
||||
|
||||
import_shared_library(libcxx-abi-shared stdc++)
|
||||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
|
||||
|
||||
import_static_library(libcxx-abi-static "${LIBCXX_CXX_ABI_LIBRARY_PATH}" stdc++)
|
||||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
|
||||
|
||||
# Link against a system-provided libsupc++
|
||||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libsupc++")
|
||||
add_library(libcxx-abi-headers INTERFACE)
|
||||
import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}"
|
||||
"cxxabi.h;bits/c++config.h;bits/os_defines.h;bits/cpu_defines.h;bits/cxxabi_tweaks.h;bits/cxxabi_forced.h")
|
||||
target_compile_definitions(libcxx-abi-headers INTERFACE "-D__GLIBCXX__")
|
||||
|
||||
import_shared_library(libcxx-abi-shared supc++)
|
||||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
|
||||
|
||||
import_static_library(libcxx-abi-static "${LIBCXX_CXX_ABI_LIBRARY_PATH}" supc++)
|
||||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
|
||||
|
||||
# Link against the in-tree libc++abi
|
||||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxabi")
|
||||
add_library(libcxx-abi-headers INTERFACE)
|
||||
target_link_libraries(libcxx-abi-headers INTERFACE cxxabi-headers)
|
||||
target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXX_BUILDING_LIBCXXABI")
|
||||
|
||||
if (TARGET cxxabi_shared)
|
||||
add_library(libcxx-abi-shared ALIAS cxxabi_shared)
|
||||
endif()
|
||||
|
||||
if (TARGET cxxabi_static)
|
||||
add_library(libcxx-abi-static ALIAS cxxabi_static)
|
||||
endif()
|
||||
|
||||
if (TARGET cxxabi_shared_objects)
|
||||
add_library(libcxx-abi-shared-objects ALIAS cxxabi_shared_objects)
|
||||
endif()
|
||||
|
||||
if (TARGET cxxabi_static_objects)
|
||||
add_library(libcxx-abi-static-objects ALIAS cxxabi_static_objects)
|
||||
endif()
|
||||
|
||||
# Link against a system-provided libc++abi
|
||||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "system-libcxxabi")
|
||||
add_library(libcxx-abi-headers INTERFACE)
|
||||
import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}" "cxxabi.h;__cxxabi_config.h")
|
||||
target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXX_BUILDING_LIBCXXABI")
|
||||
|
||||
import_shared_library(libcxx-abi-shared c++abi)
|
||||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
|
||||
|
||||
import_static_library(libcxx-abi-static "${LIBCXX_CXX_ABI_LIBRARY_PATH}" c++abi)
|
||||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
|
||||
|
||||
# Link against a system-provided libcxxrt
|
||||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "libcxxrt")
|
||||
# libcxxrt does not provide aligned new and delete operators
|
||||
# TODO: We're keeping this for backwards compatibility, but this doesn't belong here.
|
||||
set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON)
|
||||
|
||||
if(NOT LIBCXX_CXX_ABI_INCLUDE_PATHS)
|
||||
message(STATUS "LIBCXX_CXX_ABI_INCLUDE_PATHS not set, using /usr/include/c++/v1")
|
||||
set(LIBCXX_CXX_ABI_INCLUDE_PATHS "/usr/include/c++/v1")
|
||||
endif()
|
||||
add_library(libcxx-abi-headers INTERFACE)
|
||||
import_private_headers(libcxx-abi-headers "${LIBCXX_CXX_ABI_INCLUDE_PATHS}"
|
||||
"cxxabi.h;unwind.h;unwind-arm.h;unwind-itanium.h")
|
||||
target_compile_definitions(libcxx-abi-headers INTERFACE "-DLIBCXXRT")
|
||||
|
||||
import_shared_library(libcxx-abi-shared cxxrt)
|
||||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
|
||||
|
||||
import_static_library(libcxx-abi-static "${LIBCXX_CXX_ABI_LIBRARY_PATH}" cxxrt)
|
||||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
|
||||
|
||||
# Link against a system-provided vcruntime
|
||||
# FIXME: Figure out how to configure the ABI library on Windows.
|
||||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "vcruntime")
|
||||
add_library(libcxx-abi-headers INTERFACE)
|
||||
add_library(libcxx-abi-shared INTERFACE)
|
||||
add_library(libcxx-abi-static INTERFACE)
|
||||
|
||||
# Don't link against any ABI library
|
||||
elseif ("${LIBCXX_CXX_ABI}" STREQUAL "none")
|
||||
add_library(libcxx-abi-headers INTERFACE)
|
||||
target_compile_definitions(libcxx-abi-headers INTERFACE "-D_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY")
|
||||
|
||||
add_library(libcxx-abi-shared INTERFACE)
|
||||
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
|
||||
|
||||
add_library(libcxx-abi-static INTERFACE)
|
||||
target_link_libraries(libcxx-abi-static INTERFACE libcxx-abi-headers)
|
||||
endif()
|
@ -1,254 +0,0 @@
|
||||
# HandleLibcxxFlags - A set of macros used to setup the flags used to compile
|
||||
# and link libc++. These macros add flags to the following CMake variables.
|
||||
# - LIBCXX_COMPILE_FLAGS: flags used to compile libc++
|
||||
# - LIBCXX_LINK_FLAGS: flags used to link libc++
|
||||
# - LIBCXX_LIBRARIES: libraries to link libc++ to.
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
|
||||
unset(add_flag_if_supported)
|
||||
|
||||
# Mangle the name of a compiler flag into a valid CMake identifier.
|
||||
# Ex: --std=c++11 -> STD_EQ_CXX11
|
||||
macro(mangle_name str output)
|
||||
string(STRIP "${str}" strippedStr)
|
||||
string(REGEX REPLACE "^/" "" strippedStr "${strippedStr}")
|
||||
string(REGEX REPLACE "^-+" "" strippedStr "${strippedStr}")
|
||||
string(REGEX REPLACE "-+$" "" strippedStr "${strippedStr}")
|
||||
string(REPLACE "-" "_" strippedStr "${strippedStr}")
|
||||
string(REPLACE ":" "_COLON_" strippedStr "${strippedStr}")
|
||||
string(REPLACE "=" "_EQ_" strippedStr "${strippedStr}")
|
||||
string(REPLACE "+" "X" strippedStr "${strippedStr}")
|
||||
string(TOUPPER "${strippedStr}" ${output})
|
||||
endmacro()
|
||||
|
||||
# Remove a list of flags from all CMake variables that affect compile flags.
|
||||
# This can be used to remove unwanted flags specified on the command line
|
||||
# or added in other parts of LLVM's cmake configuration.
|
||||
macro(remove_flags)
|
||||
foreach(var ${ARGN})
|
||||
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL}")
|
||||
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
|
||||
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "${var}" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
string(REPLACE "${var}" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
|
||||
string(REPLACE "${var}" "" CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
string(REPLACE "${var}" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||
string(REPLACE "${var}" "" CMAKE_SHARED_MODULE_FLAGS "${CMAKE_SHARED_MODULE_FLAGS}")
|
||||
remove_definitions(${var})
|
||||
endforeach()
|
||||
endmacro(remove_flags)
|
||||
|
||||
macro(check_flag_supported flag)
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
|
||||
endmacro()
|
||||
|
||||
macro(append_flags DEST)
|
||||
foreach(value ${ARGN})
|
||||
list(APPEND ${DEST} ${value})
|
||||
list(APPEND ${DEST} ${value})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# If the specified 'condition' is true then append the specified list of flags to DEST
|
||||
macro(append_flags_if condition DEST)
|
||||
if (${condition})
|
||||
list(APPEND ${DEST} ${ARGN})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Add each flag in the list specified by DEST if that flag is supported by the current compiler.
|
||||
macro(append_flags_if_supported DEST)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
|
||||
append_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${DEST} ${flag})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Add a macro definition if condition is true.
|
||||
macro(define_if condition def)
|
||||
if (${condition})
|
||||
add_definitions(${def})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Add a macro definition if condition is not true.
|
||||
macro(define_if_not condition def)
|
||||
if (NOT ${condition})
|
||||
add_definitions(${def})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Add a macro definition to the __config_site file if the specified condition
|
||||
# is 'true'. Note that '-D${def}' is not added. Instead it is expected that
|
||||
# the build include the '__config_site' header.
|
||||
macro(config_define_if condition def)
|
||||
if (${condition})
|
||||
set(${def} ON)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(config_define_if_not condition def)
|
||||
if (NOT ${condition})
|
||||
set(${def} ON)
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
macro(config_define value def)
|
||||
set(${def} ${value})
|
||||
endmacro()
|
||||
|
||||
# Add a list of flags to all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS',
|
||||
# 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS'.
|
||||
macro(add_target_flags)
|
||||
foreach(value ${ARGN})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${value}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${value}")
|
||||
list(APPEND LIBCXX_COMPILE_FLAGS ${value})
|
||||
list(APPEND LIBCXX_LINK_FLAGS ${value})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# If the specified 'condition' is true then add a list of flags to
|
||||
# all of 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBCXX_COMPILE_FLAGS'
|
||||
# and 'LIBCXX_LINK_FLAGS'.
|
||||
macro(add_target_flags_if condition)
|
||||
if (${condition})
|
||||
add_target_flags(${ARGN})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Add all the flags supported by the compiler to all of
|
||||
# 'CMAKE_CXX_FLAGS', 'CMAKE_C_FLAGS', 'LIBCXX_COMPILE_FLAGS'
|
||||
# and 'LIBCXX_LINK_FLAGS'.
|
||||
macro(add_target_flags_if_supported)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
|
||||
add_target_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Add a specified list of flags to both 'LIBCXX_COMPILE_FLAGS' and
|
||||
# 'LIBCXX_LINK_FLAGS'.
|
||||
macro(add_flags)
|
||||
foreach(value ${ARGN})
|
||||
list(APPEND LIBCXX_COMPILE_FLAGS ${value})
|
||||
list(APPEND LIBCXX_LINK_FLAGS ${value})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# If the specified 'condition' is true then add a list of flags to both
|
||||
# 'LIBCXX_COMPILE_FLAGS' and 'LIBCXX_LINK_FLAGS'.
|
||||
macro(add_flags_if condition)
|
||||
if (${condition})
|
||||
add_flags(${ARGN})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Add each flag in the list to LIBCXX_COMPILE_FLAGS and LIBCXX_LINK_FLAGS
|
||||
# if that flag is supported by the current compiler.
|
||||
macro(add_flags_if_supported)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
|
||||
add_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Add a list of flags to 'LIBCXX_COMPILE_FLAGS'.
|
||||
macro(add_compile_flags)
|
||||
foreach(f ${ARGN})
|
||||
list(APPEND LIBCXX_COMPILE_FLAGS ${f})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# If 'condition' is true then add the specified list of flags to
|
||||
# 'LIBCXX_COMPILE_FLAGS'
|
||||
macro(add_compile_flags_if condition)
|
||||
if (${condition})
|
||||
add_compile_flags(${ARGN})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# For each specified flag, add that flag to 'LIBCXX_COMPILE_FLAGS' if the
|
||||
# flag is supported by the C++ compiler.
|
||||
macro(add_compile_flags_if_supported)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
|
||||
add_compile_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Add a list of flags to 'LIBCXX_LINK_FLAGS'.
|
||||
macro(add_link_flags)
|
||||
foreach(f ${ARGN})
|
||||
list(APPEND LIBCXX_LINK_FLAGS ${f})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# If 'condition' is true then add the specified list of flags to
|
||||
# 'LIBCXX_LINK_FLAGS'
|
||||
macro(add_link_flags_if condition)
|
||||
if (${condition})
|
||||
add_link_flags(${ARGN})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# For each specified flag, add that flag to 'LIBCXX_LINK_FLAGS' if the
|
||||
# flag is supported by the C++ compiler.
|
||||
macro(add_link_flags_if_supported)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
|
||||
add_link_flags_if(CXX_SUPPORTS_${flagname}_FLAG ${flag})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# Add a list of libraries or link flags to 'LIBCXX_LIBRARIES'.
|
||||
macro(add_library_flags)
|
||||
foreach(lib ${ARGN})
|
||||
list(APPEND LIBCXX_LIBRARIES ${lib})
|
||||
endforeach()
|
||||
endmacro()
|
||||
|
||||
# if 'condition' is true then add the specified list of libraries and flags
|
||||
# to 'LIBCXX_LIBRARIES'.
|
||||
macro(add_library_flags_if condition)
|
||||
if(${condition})
|
||||
add_library_flags(${ARGN})
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
# Turn a comma separated CMake list into a space separated string.
|
||||
macro(split_list listname)
|
||||
string(REPLACE ";" " " ${listname} "${${listname}}")
|
||||
endmacro()
|
||||
|
||||
# For each specified flag, add that link flag to the provided target.
|
||||
# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE.
|
||||
function(target_add_link_flags_if_supported target visibility)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
|
||||
if (CXX_SUPPORTS_${flagname}_FLAG)
|
||||
target_link_libraries(${target} ${visibility} ${flag})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# For each specified flag, add that compile flag to the provided target.
|
||||
# The flags are added with the given visibility, i.e. PUBLIC|PRIVATE|INTERFACE.
|
||||
function(target_add_compile_flags_if_supported target visibility)
|
||||
foreach(flag ${ARGN})
|
||||
mangle_name("${flag}" flagname)
|
||||
check_cxx_compiler_flag("${flag}" "CXX_SUPPORTS_${flagname}_FLAG")
|
||||
if (CXX_SUPPORTS_${flagname}_FLAG)
|
||||
target_compile_options(${target} ${visibility} ${flag})
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
@ -1,18 +0,0 @@
|
||||
# MACRO_ENSURE_OUT_OF_SOURCE_BUILD(<errorMessage>)
|
||||
|
||||
macro( MACRO_ENSURE_OUT_OF_SOURCE_BUILD _errorMessage )
|
||||
|
||||
string( COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _insource )
|
||||
if( _insource )
|
||||
message( SEND_ERROR "${_errorMessage}" )
|
||||
message( FATAL_ERROR
|
||||
"In-source builds are not allowed.
|
||||
CMake would overwrite the makefiles distributed with Compiler-RT.
|
||||
Please create a directory and run cmake from there, passing the path
|
||||
to this source directory as the last argument.
|
||||
This process created the file `CMakeCache.txt' and the directory `CMakeFiles'.
|
||||
Please delete them."
|
||||
)
|
||||
endif( _insource )
|
||||
|
||||
endmacro( MACRO_ENSURE_OUT_OF_SOURCE_BUILD )
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
|
||||
set(CMAKE_CXX_COMPILER_TARGET "aarch64-linux-gnu" CACHE STRING "")
|
@ -1,19 +0,0 @@
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "")
|
||||
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON CACHE BOOL "")
|
||||
set(CMAKE_C_FLAGS "-D__LIBC_NO_CPP_MATH_OVERLOADS__" CACHE STRING "")
|
||||
set(CMAKE_CXX_FLAGS "-D__LIBC_NO_CPP_MATH_OVERLOADS__" CACHE STRING "")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,-G -Wl,-bcdtors:all:-2147483548:s" CACHE STRING "")
|
||||
set(CMAKE_AR "/usr/bin/ar" CACHE FILEPATH "")
|
||||
|
||||
set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_ASSERTIONS OFF CACHE BOOL "")
|
||||
set(LIBCXX_ABI_VERSION "1" CACHE STRING "")
|
||||
set(LIBCXX_ENABLE_ABI_LINKER_SCRIPT OFF CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_SHARED ON CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_STATIC OFF CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_SHARED ON CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_STATIC OFF CACHE BOOL "")
|
||||
set(LIBCXX_CXX_ABI libcxxabi CACHE STRING "")
|
||||
set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
|
||||
set(LIBUNWIND_ENABLE_SHARED ON CACHE BOOL "")
|
||||
set(LIBUNWIND_ENABLE_STATIC OFF CACHE BOOL "")
|
@ -1,38 +0,0 @@
|
||||
# Use CMake's built-in Android NDK support. This will also use the compiler from
|
||||
# the NDK.
|
||||
|
||||
set(CMAKE_ANDROID_NDK "$ENV{ANDROID_NDK_HOME}" CACHE STRING "")
|
||||
set(CMAKE_SYSTEM_NAME Android CACHE STRING "")
|
||||
|
||||
# Default architecture and Android API level. Selecting a much earlier API may
|
||||
# require adding a toybox build to the device's PATH.
|
||||
set(CMAKE_ANDROID_ARCH_ABI "x86_64" CACHE STRING "")
|
||||
set(CMAKE_SYSTEM_VERSION 21 CACHE STRING "")
|
||||
|
||||
# Rename libc++.so to libc++_shared.so to ensure that it doesn't interfere with
|
||||
# the libc++.so on the device, then use LD_LIBRARY_PATH to point test
|
||||
# executables at the library. Also rename the static library for consistency
|
||||
# and to help prevent -lc++ from linking libc++.a.
|
||||
set(LIBCXX_SHARED_OUTPUT_NAME c++_shared CACHE STRING "")
|
||||
set(LIBCXX_STATIC_OUTPUT_NAME c++_static CACHE STRING "")
|
||||
|
||||
# Use a different C++ namespace for the NDK libc++_shared.so to help avoid
|
||||
# symbol conflicts on older versions of Android.
|
||||
set(LIBCXX_ABI_NAMESPACE __test CACHE STRING "")
|
||||
|
||||
# The build doesn't add a suffix to an Android shared object filename, so it
|
||||
# writes both a libc++_shared.so ELF file and a libc++_shared.so linker script
|
||||
# to the same output path (the script clobbers the binary). Turn off the linker
|
||||
# script.
|
||||
set(LIBCXX_ENABLE_ABI_LINKER_SCRIPT OFF CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY ON CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
|
||||
|
||||
# Use adb to push tests to a locally-connected device (e.g. emulator) and run them.
|
||||
set(LIBCXX_TEST_CONFIG "llvm-libc++-android-ndk.cfg.in" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_CONFIG "llvm-libc++abi-android-ndk.cfg.in" CACHE STRING "")
|
||||
|
||||
# CMAKE_SOURCE_DIR refers to the "<monorepo>/runtimes" directory.
|
||||
set(LIBCXX_EXECUTOR "${CMAKE_SOURCE_DIR}/../libcxx/utils/adb_run.py" CACHE STRING "")
|
||||
set(LIBCXXABI_EXECUTOR "${LIBCXX_EXECUTOR}" CACHE STRING "")
|
@ -1,21 +0,0 @@
|
||||
set(CMAKE_BUILD_TYPE MinSizeRel CACHE STRING "")
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE OFF CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_USE_COMPILER_RT ON CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_ASSERTIONS OFF CACHE BOOL "")
|
||||
set(LIBCXX_ABI_VERSION "1" CACHE STRING "")
|
||||
set(LIBCXX_ENABLE_STATIC ON CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_SHARED ON CACHE BOOL "")
|
||||
set(LIBCXX_CXX_ABI libcxxabi CACHE STRING "")
|
||||
set(LIBCXX_ENABLE_VENDOR_AVAILABILITY_ANNOTATIONS ON CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "")
|
||||
set(LIBCXXABI_HERMETIC_STATIC_LIBRARY ON CACHE BOOL "")
|
||||
|
||||
set(LIBCXXABI_ENABLE_ASSERTIONS OFF CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_FORGIVING_DYNAMIC_CAST ON CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_TEST_CONFIG "apple-libc++-shared.cfg.in" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_CONFIG "apple-libc++abi-shared.cfg.in" CACHE STRING "")
|
||||
set(LIBCXX_TEST_PARAMS "stdlib=apple-libc++" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1,4 +0,0 @@
|
||||
set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
|
||||
set(CMAKE_CXX_COMPILER_TARGET "armv7l-linux-gnueabihf" CACHE STRING "")
|
||||
set(CMAKE_CXX_FLAGS "-marm" CACHE STRING "")
|
||||
set(CMAKE_C_FLAGS "-marm" CACHE STRING "")
|
@ -1,6 +0,0 @@
|
||||
set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
|
||||
set(CMAKE_CXX_COMPILER_TARGET "armv7l-linux-gnueabihf" CACHE STRING "")
|
||||
set(CMAKE_CXX_FLAGS "-mthumb" CACHE STRING "")
|
||||
set(CMAKE_C_FLAGS "-mthumb" CACHE STRING "")
|
||||
set(LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "")
|
@ -1,4 +0,0 @@
|
||||
set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
|
||||
set(CMAKE_CXX_COMPILER_TARGET "armv8l-linux-gnueabihf" CACHE STRING "")
|
||||
set(CMAKE_CXX_FLAGS "-marm" CACHE STRING "")
|
||||
set(CMAKE_C_FLAGS "-marm" CACHE STRING "")
|
@ -1,6 +0,0 @@
|
||||
set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
|
||||
set(CMAKE_CXX_COMPILER_TARGET "armv8l-linux-gnueabihf" CACHE STRING "")
|
||||
set(CMAKE_CXX_FLAGS "-mthumb" CACHE STRING "")
|
||||
set(CMAKE_C_FLAGS "-mthumb" CACHE STRING "")
|
||||
set(LIBCXX_ENABLE_EXCEPTIONS OFF CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_EXCEPTIONS OFF CACHE BOOL "")
|
@ -1,9 +0,0 @@
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "")
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON CACHE BOOL "")
|
||||
|
||||
set(LIBCXX_ENABLE_ASSERTIONS OFF CACHE BOOL "")
|
||||
set(LIBCXX_ABI_VERSION "1" CACHE STRING "")
|
||||
set(LIBCXX_ENABLE_STATIC ON CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_SHARED ON CACHE BOOL "")
|
||||
set(LIBCXX_CXX_ABI libcxxrt CACHE STRING "")
|
||||
set(LIBCXX_ENABLE_NEW_DELETE_DEFINITIONS ON CACHE BOOL "")
|
@ -1 +0,0 @@
|
||||
set(LIBCXX_ABI_UNSTABLE ON CACHE BOOL "")
|
@ -1,3 +0,0 @@
|
||||
set(LLVM_USE_SANITIZER "Address" CACHE STRING "")
|
||||
# This is a temporary (hopefully) workaround for an ASan issue (see https://llvm.org/D119410).
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -asan-use-private-alias=1" CACHE INTERNAL "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_ENABLE_ASSERTIONS ON CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_ASSERTIONS ON CACHE BOOL "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_TEST_PARAMS "std=c++03" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_TEST_PARAMS "std=c++11" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_TEST_PARAMS "std=c++14" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_TEST_PARAMS "std=c++17" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_TEST_PARAMS "std=c++20" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_TEST_PARAMS "std=c++2b" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1 +0,0 @@
|
||||
set(LIBCXX_ENABLE_DEBUG_MODE ON CACHE BOOL "")
|
@ -1,12 +0,0 @@
|
||||
# Build a libc++ shared library, but merge libc++abi and libunwind into it.
|
||||
set(LIBCXX_ENABLE_SHARED ON CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_ABI_LINKER_SCRIPT OFF CACHE BOOL "")
|
||||
set(LIBCXX_ENABLE_STATIC_ABI_LIBRARY ON CACHE BOOL "")
|
||||
set(LIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY ON CACHE BOOL "")
|
||||
|
||||
set(LIBCXXABI_ENABLE_SHARED OFF CACHE BOOL "")
|
||||
set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
|
||||
set(LIBCXXABI_ENABLE_STATIC_UNWINDER ON CACHE BOOL "")
|
||||
set(LIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY ON CACHE BOOL "")
|
||||
|
||||
set(LIBUNWIND_ENABLE_SHARED OFF CACHE BOOL "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_TEST_PARAMS "enable_modules=True" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1 +0,0 @@
|
||||
set(LLVM_USE_SANITIZER "MemoryWithOrigins" CACHE STRING "")
|
@ -1,2 +0,0 @@
|
||||
set(LIBCXX_TEST_PARAMS "enable_experimental=False" CACHE STRING "")
|
||||
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
|
@ -1 +0,0 @@
|
||||
set(LIBCXX_ENABLE_FILESYSTEM OFF CACHE BOOL "")
|
@ -1 +0,0 @@
|
||||
set(LIBCXX_ENABLE_FSTREAM OFF CACHE BOOL "")
|
@ -1 +0,0 @@
|
||||
set(LIBCXX_ENABLE_LOCALIZATION OFF CACHE BOOL "")
|
@ -1 +0,0 @@
|
||||
set(LIBCXX_ENABLE_RANDOM_DEVICE OFF CACHE BOOL "")
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user