72 Commits
v2.0.0 ... main

Author SHA1 Message Date
snake-4
8832d695ac Improved unmount logic (#93) 2025-08-01 19:18:35 +02:00
VisionR1
3ef02e5d28 Update README.md (#92)
Proper info, in the section about KernelSU & APatch.
2025-08-01 19:12:21 +02:00
snake-4
847d7fb255 Updated update_metadata 2025-02-23 01:19:45 +01:00
snake-4
1013f8af3d Bumped version to 2.1.4 2025-02-23 01:14:19 +01:00
snake-4
e8c20fb39d Fixed CI workflow 2025-02-23 01:11:32 +01:00
snake-4
740dfc9b3d Respect default errors value on EXT FS 2025-02-23 01:00:04 +01:00
snake-4
60e1cc4e8f Sync boot scripts to PlayIntegrityFork 1493650 2025-02-22 18:48:24 +01:00
snake-4
59c2a442c7 Updated submodule dependencies 2025-02-22 18:47:36 +01:00
snake-4
9497e7f1cb Changed build directory 2025-02-22 18:42:15 +01:00
snake-4
5f863b672c Updated NDK, AGP and Gradle 2025-02-22 18:42:06 +01:00
snake-4
1304dca810 Sync boot scripts to PlayIntegrityFork b427736 2024-09-05 00:02:01 +02:00
snake-4
8b20a94392 Updated service.sh 2024-08-17 21:05:32 +02:00
snake-4
a191eaad10 Update update.json 2024-08-17 16:35:25 +02:00
snake-4
7b35d3645c Bumped version to 2.1.3 2024-08-17 16:24:48 +02:00
snake-4
b3767f77c9 Added new props to service.sh 2024-08-17 16:22:37 +02:00
snake-4
6f14306f1f Updated NDK, AGP and Gradle 2024-08-17 15:40:14 +02:00
snake-4
9cdb7976f4 Removed mount ID regeneration 2024-08-17 14:53:14 +02:00
snake-4
6172b38ce0 Fixed prop scripts for Xiaomi devices 2024-08-17 14:51:20 +02:00
snake-4
3b8ec9b33f Update update.json 2024-08-03 05:10:44 +02:00
snake-4
8878c9f704 Bumped version to 2.1.2 2024-08-03 05:06:47 +02:00
Chris Renshaw
447f127321 Add global sensitive props scripts (#57)
Please see
https://github.com/osm0sis/PlayIntegrityFork/tree/main/module
and
https://github.com/Displax/safetynet-fix/tree/dev/magisk
for full commit history and attribution/authorship
2024-08-02 02:20:40 +03:00
snake-4
0ed0a59b1e Updated submodules, system_properties tracks TJW repo 2024-06-15 17:57:42 +02:00
snake-4
d341cce3e7 POSIX compliant type names 2024-06-15 17:48:41 +02:00
snake-4
1f2e9d34fc Regenerate mount IDs
closes #23.
2024-06-05 23:38:55 +03:00
snake-4
0d0c8c9485 Using forked system_properties 2024-06-05 22:03:25 +03:00
snake-4
532352131c Update update.json 2024-05-09 16:31:44 +02:00
snake-4
8c1d7f55dc Bumped version to 2.1.1 2024-05-09 16:17:57 +02:00
snake-4
9c06b69c42 Changes to companion fork 2024-05-07 05:42:57 +02:00
snake-4
6530a5a011 Added FD reopener 2024-05-05 06:22:46 +02:00
snake-4
a7dd49f2a9 Added +x to gradlew 2024-05-03 20:10:56 +02:00
snake-4
02aae1bbd7 Fixed memory safety of prop hider 2024-05-03 19:54:40 +02:00
snake-4
8c7f376f16 Misc build system and CI changes 2024-05-03 18:10:02 +02:00
snake-4
3a72258df4 Added prop hiding 2024-05-03 03:21:09 +02:00
snake-4
b6603b12c2 Misc changes 2024-05-03 03:21:09 +02:00
snake-4
0e77d8385d Update issue templates 2024-04-30 17:15:29 +02:00
snake-4
7cbb41bbb6 Added mountinfo_root_resolver and removed...
mount_parser.
2024-04-28 14:09:15 +02:00
snake-4
2a31d654a6 Updated GitHub CI workflow...
and changed a log message.
2024-04-27 18:48:50 +02:00
snake-4
5c2ba2a95d Fixed companion NS and moved code to namespaces 2024-04-27 17:15:32 +02:00
snake-4
e431fc2c6a Added cache for parsers 2024-04-27 16:56:50 +02:00
snake-4
8c4fbcc207 Added libcxx as submodule 2024-04-24 09:03:42 +02:00
snake-4
289aa9808e Removed libcxx from the repo 2024-04-24 09:01:54 +02:00
snake-4
266540b012 Update update.json 2024-04-24 08:33:52 +02:00
snake-4
72f96df644 Bumped version to 2.1.0 2024-04-24 08:29:08 +02:00
snake-4
e03060eb22 Added Zygisk hide for 27.0 and renamed unmount.cpp 2024-04-24 07:45:04 +02:00
snake-4
71eee6bf92 Added ELFIO submodule 2024-04-24 07:01:50 +02:00
snake-4
29d4adca9e Changes to build system 2024-04-22 01:57:38 +02:00
snake-4
c0246483b0 Fixed companion FD for child zygotes 2024-04-17 00:27:40 +02:00
snake-4
e22e81d792 Updated AGP to 8.3.2...
and misc changes.
2024-04-16 23:16:21 +02:00
snake-4
5e8a2c4631 Added setresuid hook for older Android versions 2024-04-16 22:43:03 +02:00
snake-4
a7701e8b11 Updated logs and remount logic 2024-04-16 21:08:45 +02:00
snake-4
f200aa4561 Added root companion and logging macros 2024-04-16 21:08:10 +02:00
snake-4
2962997439 Moved unmount to unshare hook
This might break older Android versions. Not sure.
2024-04-16 21:07:47 +02:00
snake-4
6a61f6a4b6 Renamed some functions 2024-04-14 18:37:38 +02:00
snake-4
6e333581fb Added remount function and changed bind mount...
prefix.
2024-04-14 16:23:38 +02:00
snake-4
ac910f0ebe Unhook unshare at postAppSpecialize 2024-04-14 16:21:52 +02:00
snake-4
df3e492391 Update update.json 2024-04-12 12:50:47 +02:00
snake-4
7ec3214927 Bumped version to 2.0.4 2024-04-12 12:43:42 +02:00
snake-4
c797376230 Update main.cpp 2024-04-10 00:52:12 +02:00
snake-4
33a9ff93f4 Updated ci.yml and fixed build 2024-04-09 23:07:04 +02:00
snake-4
6f4d78b0fc Added maps parser and fixed child zygote namespaces 2024-04-09 22:35:40 +02:00
snake-4
08547864cd Added missing header guards, bumped to C++20 2024-04-09 20:32:28 +02:00
snake-4
d59ac2bf26 Updated AGP and compileSdkVersion 2024-04-09 05:34:27 +02:00
snake-4
52e5771205 Updated AGP to 8.3.0 2024-04-06 20:17:39 +02:00
snake-4
ce278b37f7 Update update.json 2024-04-01 05:10:13 +02:00
snake-4
fe05fbd621 Bumped version to v2.0.3 2024-04-01 05:05:17 +02:00
snake-4
83f2880922 Added mountinfo parser and bind mount hiding
closes #3
2024-04-01 04:58:18 +02:00
snake-4
112c4027fe Update update.json 2024-04-01 02:02:14 +02:00
snake-4
aa9a8a04e3 Bumped version to v2.0.2 2024-04-01 01:58:09 +02:00
snake-4
670767a82b Added exception for hosts bind mount 2024-04-01 01:33:12 +02:00
snake-4
7200b77043 Fixed module template copy task during build
Fixes Magisk compatibility.
2024-04-01 01:23:58 +02:00
snake-4
a07e62fcd7 Create update.json 2024-03-31 23:20:22 +02:00
snake-4
0ee57d586f Added updateJson in module.prop, bumped to v2.0.1 2024-03-31 23:15:32 +02:00
9064 changed files with 1140 additions and 1080779 deletions

30
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,30 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
<!--- Before making a bug report, please make sure you're using the latest DEBUG build from here https://github.com/snake-4/Zygisk-Assistant/actions -->
**Describe the bug**
<!--- Type a clear and concise description of what the bug is below. -->
**Steps To Reproduce**
<!--- Type the steps to reproduce the bug below. -->
1.
2.
3.
**Context**
<!--- Type the details of your device below. -->
- Device:
- OS:
- Version of Magisk, KSU or APatch:
- Other Root Module(s): None
- LSPosed Module(s): None
**Logcat**
<!--- If applicable, run `adb logcat > log.txt` on your PC and upload the `log.txt` here. -->

View File

@@ -1,52 +1,50 @@
name: CI
on:
workflow_dispatch:
push:
branches: [ main ]
tags: [ v* ]
pull_request:
merge_group:
on: [push]
permissions:
contents: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
submodules: "recursive"
fetch-depth: 0
- name: Setup Java
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"
java-version: 17
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3
- name: Build with Gradle
run: |
chmod +x ./gradlew
./gradlew zipRelease
./gradlew zipDebug
run: ./gradlew moduleZipRelease moduleZipDebug
- name: Prepare artifact
- name: Set CI Variables
if: success()
id: prepareArtifact
run: |
releaseName=`ls module/build/outputs/release/*-release.zip | awk -F '(/|.zip)' '{print $5}'` && echo "releaseName=$releaseName" >> $GITHUB_OUTPUT
debugName=`ls module/build/outputs/release/*-debug.zip | awk -F '(/|.zip)' '{print $5}'` && echo "debugName=$debugName" >> $GITHUB_OUTPUT
unzip module/build/outputs/release/*-release.zip -d extracted-release
unzip module/build/outputs/release/*-debug.zip -d extracted-debug
echo "releaseName=$(basename module/build/outputs/zip/*-release.zip .zip)" >> $GITHUB_OUTPUT
echo "debugName=$(basename module/build/outputs/zip/*-debug.zip .zip)" >> $GITHUB_OUTPUT
- name: Upload release
uses: actions/upload-artifact@v3
- name: Upload Release Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.prepareArtifact.outputs.releaseName }}
path: "./extracted-release/*"
path: "module/build/outputs/zip/release"
- name: Upload debug
uses: actions/upload-artifact@v3
- name: Upload Debug Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ steps.prepareArtifact.outputs.debugName }}
path: "./extracted-debug/*"
path: "module/build/outputs/zip/debug"
- name: Create a release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: module/build/outputs/zip/*.zip

11
.gitmodules vendored
View File

@@ -1,3 +1,12 @@
[submodule "libcxx"]
[submodule "module/jni/elfio"]
path = module/jni/elfio
url = https://github.com/serge1/ELFIO.git
[submodule "module/jni/libcxx"]
path = module/jni/libcxx
url = https://github.com/topjohnwu/libcxx.git
[submodule "module/jni/aosp_fd_utils"]
path = module/jni/aosp_fd_utils
url = https://github.com/snake-4/aosp_fd_utils.git
[submodule "module/jni/aosp_system_properties"]
path = module/jni/aosp_system_properties
url = https://github.com/topjohnwu/system_properties

View File

@@ -1,7 +1,7 @@
<h3 align="center">Zygisk Assistant</h3>
<p align="center">
A Zygisk module that hides root by unmounting suspicious mounts in user-mode.
A Zygisk module that aims to hide the existence root and Zygisk.
<br />
<br />
<a href="https://github.com/snake-4/Zygisk-Assistant/issues">Report Bug</a>
@@ -16,7 +16,18 @@
<!-- ABOUT THE PROJECT -->
## About The Project
This module creates a new transparent namespace for each application in preAppSpecialize and unmounts common root mounts.
Using the **release** build is recommended over the debug build. Only use debug builds if you are going to make a bug report.
### KernelSU & APatch users:
1. Install ZygiskNext.
1. Make sure the option `Umount modules/Exclude modifications` is enabled for the target app in the KernelSU/APatch Manager.
1. Disable `Enforce DenyList` in ZygiskNext settings if there is one.
### Magisk users:
1. Update your Magisk to 27.0 or newer for better hiding capabilities. (optional)
1. Turn on Zygisk in Magisk settings.
1. Turn off `Enforce DenyList` in Magisk settings.
1. Add the target app to the deny list unless you're using a Magisk fork with a white list instead.
<!-- CONTRIBUTING -->
@@ -37,4 +48,4 @@ Don't forget to give the project a star! Thanks again!
<!-- LICENSE -->
## License
Distributed under the MIT License. See `LICENSE` for more information.
Distributed under the MIT License. See `LICENSE` for more information.

View File

@@ -1,20 +1,17 @@
import java.io.ByteArrayOutputStream
plugins {
alias(libs.plugins.agp.lib) apply false
id("com.android.library") version "8.8.1" apply false
}
val commitHash: String by extra({
val stdout = ByteArrayOutputStream()
rootProject.exec {
commandLine("git", "rev-parse", "--short", "HEAD")
standardOutput = stdout
val commitHash: String by extra {
val result = providers.exec {
commandLine("git", "rev-parse", "--verify", "--short", "HEAD")
}
stdout.toString().trim()
})
result.standardOutput.asText.get().trim()
}
val moduleId by extra("zygisk-assistant")
val moduleName by extra("Zygisk Assistant")
val verName by extra("v2.0.0")
val verCode by extra(200)
val abiList by extra(listOf("armeabi-v7a","arm64-v8a","x86","x86_64"))
val verName by extra("v2.1.4")
val verCode by extra(214)

View File

@@ -1,5 +0,0 @@
[versions]
agp = "8.2.0"
[plugins]
agp-lib = { id = "com.android.library", version.ref = "agp" }

View File

@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

0
gradlew vendored Normal file → Executable file
View File

View File

@@ -1,7 +1,7 @@
import android.databinding.tool.ext.capitalizeUS
plugins {
alias(libs.plugins.agp.lib)
id("com.android.library")
}
val moduleId: String by rootProject.extra
@@ -13,12 +13,10 @@ val abiList: List<String> by rootProject.extra
android {
namespace = "com.example.library"
compileSdkVersion = "android-31"
compileSdkVersion = "android-34"
ndkVersion = "28.0.13004108"
defaultConfig {
minSdk = 21
ndk {
abiFilters.addAll(abiList)
}
externalNativeBuild {
ndkBuild {
arguments("-j${Runtime.getRuntime().availableProcessors()}")
@@ -37,12 +35,12 @@ androidComponents.onVariants { variant ->
val variantCapped = variant.name.capitalizeUS()
val buildTypeLowered = variant.buildType?.lowercase()
val libOutDir = layout.buildDirectory.dir("intermediates/stripped_native_libs/$variantLowered/out/lib").get()
val moduleDir = layout.buildDirectory.dir("outputs/module/$variantLowered").get()
val zipOutDir = layout.buildDirectory.dir("outputs/release").get()
val libOutDir = layout.buildDirectory.dir("intermediates/stripped_native_libs/$variantLowered/strip${variantCapped}DebugSymbols/out/lib").get()
val moduleDir = layout.buildDirectory.dir("outputs/zip/$variantLowered").get()
val zipOutDir = layout.buildDirectory.dir("outputs/zip/").get()
val zipFileName = "$moduleName-$verName-$commitHash-$buildTypeLowered.zip".replace(' ', '-')
val prepareModuleFilesTask = task<Sync>("prepareModuleFiles$variantCapped") {
val moduleFilesTask = task<Sync>("moduleFiles$variantCapped") {
group = "module"
dependsOn("assemble$variantCapped")
into(moduleDir)
@@ -55,6 +53,9 @@ androidComponents.onVariants { variant ->
"versionCode" to verCode
)
}
from("$projectDir/template") {
exclude("module.prop")
}
from(libOutDir) {
into("zygisk")
}
@@ -68,9 +69,9 @@ androidComponents.onVariants { variant ->
}
}
task<Zip>("zip$variantCapped") {
task<Zip>("moduleZip$variantCapped") {
group = "module"
dependsOn(prepareModuleFilesTask)
dependsOn(moduleFilesTask)
archiveFileName.set(zipFileName)
destinationDirectory.set(zipOutDir)
from(moduleDir)

View File

@@ -1,11 +1,13 @@
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/elfio
LOCAL_MODULE := zygisk
LOCAL_SRC_FILES := mount_parser.cpp unmount.cpp main.cpp
LOCAL_STATIC_LIBRARIES := libcxx
LOCAL_SRC_FILES := fd_reopener.cpp utils.cpp map_parser.cpp mountinfo_parser.cpp modules.cpp main.cpp
LOCAL_STATIC_LIBRARIES := libcxx libsystemproperties libfdutils
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
include jni/libcxx/Android.mk
include jni/libcxx/Android.mk
include jni/aosp_system_properties/Android.mk
include jni/aosp_fd_utils/Android.mk

View File

@@ -1,4 +1,4 @@
APP_ABI := armeabi-v7a arm64-v8a x86 x86_64
APP_CPPFLAGS := -std=c++14 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden
APP_CPPFLAGS := -std=c++20 -fno-exceptions -fno-rtti -fvisibility=hidden -fvisibility-inlines-hidden
APP_STL := none
APP_PLATFORM := android-31
APP_PLATFORM := android-34

1
module/jni/elfio Submodule

Submodule module/jni/elfio added at 34d2c64237

View File

@@ -0,0 +1,33 @@
#include "fd_reopener.hpp"
#include <fd_utils.h>
#include <string>
#include <utility>
#include "logging.hpp"
FDReopener::ScopedRegularReopener::ScopedRegularReopener()
{
auto pFdSet = GetOpenFds([](const std::string &error)
{ LOGE("GetOpenFds: %s", error.c_str()); });
if (pFdSet)
{
for (const auto &fd : *pFdSet)
{
auto pFDI = FileDescriptorInfo::CreateFromFd(fd, [fd](const std::string &error)
{ LOGE("CreateFromFd(%d): %s", fd, error.c_str()); });
// Only process regular files that are not memfds
if (pFDI && !pFDI->is_sock && !pFDI->file_path.starts_with("/memfd:"))
fdi_vector.emplace_back(std::move(pFDI));
}
}
}
FDReopener::ScopedRegularReopener::~ScopedRegularReopener()
{
for (const auto &pFDI : fdi_vector)
{
LOGD("Reopening FD %d with %s", pFDI->fd, pFDI->file_path.c_str());
pFDI->ReopenOrDetach([fd = pFDI->fd](const std::string &error)
{ LOGE("ReopenOrDetach(%d): %s", fd, error.c_str()); });
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* This file is consumed by build/tools/fs_config and is used
* for generating various files. Anything #define AID_<name>
@@ -33,20 +32,16 @@
* passwd and group files. There are ranges in this file reserved for AIDs for each 3rd party
* partition, from which the system reads passwd and group files.
*/
#pragma once
/* This is the main Users and Groups config for the platform.
* DO NOT EVER RENUMBER
*/
#define AID_ROOT 0 /* traditional unix root user */
/* The following are for LTP and should only be used for testing */
#define AID_DAEMON 1 /* traditional unix daemon owner */
#define AID_BIN 2 /* traditional unix binaries owner */
/* The following are for tests like LTP and should only be used for testing. */
#define AID_DAEMON 1 /* Traditional unix daemon owner. */
#define AID_BIN 2 /* Traditional unix binaries owner. */
#define AID_SYS 3 /* A group with the same gid on Linux/macOS/Android. */
#define AID_SYSTEM 1000 /* system server */
#define AID_RADIO 1001 /* telephony subsystem, RIL */
#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
#define AID_GRAPHICS 1003 /* graphics devices */
@@ -127,12 +122,22 @@
#define AID_EXT_DATA_RW 1078 /* GID for app-private data directories on external storage */
#define AID_EXT_OBB_RW 1079 /* GID for OBB directories on external storage */
#define AID_CONTEXT_HUB 1080 /* GID for access to the Context Hub */
#define AID_VIRTUALIZATIONSERVICE 1081 /* VirtualizationService daemon */
#define AID_ARTD 1082 /* ART Service daemon */
#define AID_UWB 1083 /* UWB subsystem */
#define AID_THREAD_NETWORK 1084 /* Thread Network subsystem */
#define AID_DICED 1085 /* Android's DICE daemon */
#define AID_DMESGD 1086 /* dmesg parsing daemon for kernel report collection */
#define AID_JC_WEAVER 1087 /* Javacard Weaver HAL - to manage omapi ARA rules */
#define AID_JC_STRONGBOX 1088 /* Javacard Strongbox HAL - to manage omapi ARA rules */
#define AID_JC_IDENTITYCRED 1089 /* Javacard Identity Cred HAL - to manage omapi ARA rules */
#define AID_SDK_SANDBOX 1090 /* SDK sandbox virtual UID */
#define AID_SECURITY_LOG_WRITER 1091 /* write to security log */
#define AID_PRNG_SEEDER 1092 /* PRNG seeder daemon */
/* Changes to this file must be made in AOSP, *not* in internal branches. */
#define AID_SHELL 2000 /* adb and debug shell user */
#define AID_CACHE 2001 /* cache access */
#define AID_DIAG 2002 /* access to diagnostic resources */
/* The range 2900-2999 is reserved for the vendor partition */
/* Note that the two 'OEM' ranges pre-dated the vendor partition, so they take the legacy 'OEM'
* name. Additionally, they pre-dated passwd/group files, so there are users and groups named oem_#
@@ -141,7 +146,6 @@
* value. */
#define AID_OEM_RESERVED_START 2900
#define AID_OEM_RESERVED_END 2999
/* The 3000 series are intended for use as supplemental group id's only.
* They indicate special Android capabilities that the kernel is aware of. */
#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */
@@ -154,47 +158,36 @@
#define AID_READPROC 3009 /* Allow /proc read access */
#define AID_WAKELOCK 3010 /* Allow system wakelock read/write access */
#define AID_UHID 3011 /* Allow read/write to /dev/uhid node */
#define AID_READTRACEFS 3012 /* Allow tracefs read */
/* The range 5000-5999 is also reserved for vendor partition. */
#define AID_OEM_RESERVED_2_START 5000
#define AID_OEM_RESERVED_2_END 5999
/* The range 6000-6499 is reserved for the system partition. */
#define AID_SYSTEM_RESERVED_START 6000
#define AID_SYSTEM_RESERVED_END 6499
/* The range 6500-6999 is reserved for the odm partition. */
#define AID_ODM_RESERVED_START 6500
#define AID_ODM_RESERVED_END 6999
/* The range 7000-7499 is reserved for the product partition. */
#define AID_PRODUCT_RESERVED_START 7000
#define AID_PRODUCT_RESERVED_END 7499
/* The range 7500-7999 is reserved for the system_ext partition. */
#define AID_SYSTEM_EXT_RESERVED_START 7500
#define AID_SYSTEM_EXT_RESERVED_END 7999
#define AID_EVERYBODY 9997 /* shared between all apps in the same profile */
#define AID_MISC 9998 /* access to misc storage */
#define AID_NOBODY 9999
#define AID_APP 10000 /* TODO: switch users over to AID_APP_START */
#define AID_APP_START 10000 /* first app user */
#define AID_APP_END 19999 /* last app user */
#define AID_CACHE_GID_START 20000 /* start of gids for apps to mark cached data */
#define AID_CACHE_GID_END 29999 /* end of gids for apps to mark cached data */
#define AID_EXT_GID_START 30000 /* start of gids for apps to mark external data */
#define AID_EXT_GID_END 39999 /* end of gids for apps to mark external data */
#define AID_EXT_CACHE_GID_START 40000 /* start of gids for apps to mark external cached data */
#define AID_EXT_CACHE_GID_END 49999 /* end of gids for apps to mark external cached data */
#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
#define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */
/*
* This is a magic number in the kernel and not something that was picked
* arbitrarily. This value is returned whenever a uid that has no mapping in the
@@ -202,14 +195,14 @@
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/linux/highuid.h?h=v4.4#n40
*/
#define AID_OVERFLOWUID 65534 /* unmapped user in the user namespace */
/* use the ranges below to determine whether a process is sdk sandbox */
#define AID_SDK_SANDBOX_PROCESS_START 20000 /* start of uids allocated to sdk sandbox processes */
#define AID_SDK_SANDBOX_PROCESS_END 29999 /* end of uids allocated to sdk sandbox processes */
/* use the ranges below to determine whether a process is isolated */
#define AID_ISOLATED_START 90000 /* start of uids for fully isolated sandboxed processes */
#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
#define AID_USER 100000 /* TODO: switch users over to AID_USER_OFFSET */
#define AID_USER_OFFSET 100000 /* offset for uid ranges for each user */
/*
* android_ids has moved to pwd/grp functionality.
* If you need to add one, the structure is now

View File

@@ -0,0 +1,19 @@
#pragma once
#include "fd_utils.h"
#include <vector>
#include <memory>
namespace FDReopener
{
class ScopedRegularReopener
{
public:
ScopedRegularReopener();
~ScopedRegularReopener();
private:
ScopedRegularReopener(const ScopedRegularReopener &);
void operator=(const ScopedRegularReopener &);
std::vector<std::unique_ptr<FileDescriptorInfo>> fdi_vector;
};
}

View File

@@ -1,15 +1,16 @@
#pragma once
#include <android/log.h>
#include <string.h>
#include <errno.h>
#include <cstring>
#include <cerrno>
#include <cinttypes>
#ifndef NDEBUG
static constexpr auto TAG = "ZygiskAssistant/JNI";
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
#else
#define LOGD(...)
#define LOGI(...)
#define LOGW(...)
#define LOGE(...)
#endif

View File

@@ -0,0 +1,31 @@
#pragma once
#include <sstream>
#include <string>
#include <vector>
#include <sys/types.h>
namespace Parsers
{
class map_entry
{
public:
map_entry(uintptr_t address_start, uintptr_t address_end, uintptr_t offset,
const std::string &perms, const std::string &pathname, dev_t device, ino_t inode);
uintptr_t getAddressStart() const;
uintptr_t getAddressEnd() const;
const std::string &getPerms() const;
uintptr_t getOffset() const;
dev_t getDevice() const;
ino_t getInode() const;
const std::string &getPathname() const;
private:
uintptr_t address_start, address_end, offset;
std::string perms, pathname;
dev_t device;
ino_t inode;
};
const std::vector<map_entry> &parseSelfMaps(bool cached = true);
}

View File

@@ -0,0 +1,6 @@
#pragma once
void doUnmount();
void doRemount();
void doHideZygisk();
void doMrProp();

View File

@@ -1,29 +0,0 @@
#include <string>
#include <vector>
#include <unordered_map>
#include <mntent.h>
class mount_entry_t
{
public:
mount_entry_t(::mntent *entry);
const std::string &getFsName() const;
const std::string &getMountPoint() const;
const std::string &getType() const;
const std::unordered_map<std::string, std::string> &getOptions() const;
int getDumpFrequency() const;
int getPassNumber() const;
private:
void parseMountOptions(const std::string &input);
std::string fsname;
std::string dir;
std::string type;
std::unordered_map<std::string, std::string> opts_map;
int freq;
int passno;
};
std::vector<mount_entry_t> parseMountsFromPath(const char *path);

View File

@@ -0,0 +1,47 @@
#pragma once
#include <string>
#include <vector>
#include <unordered_map>
#include <sys/types.h>
namespace Parsers
{
class mountinfo_entry
{
public:
mountinfo_entry(int mount_id, int parent_id, dev_t device,
const std::string &root, const std::string &mount_point,
const std::string &mount_options, const std::string &optional_fields,
const std::string &filesystem_type, const std::string &mount_source,
const std::string &super_options);
int getMountId() const;
int getParentId() const;
dev_t getDevice() const;
const std::string &getRoot() const;
const std::string &getMountPoint() const;
const std::unordered_map<std::string, std::string> &getMountOptions() const;
const std::string &getOptionalFields() const;
const std::string &getFilesystemType() const;
const std::string &getMountSource() const;
const std::unordered_map<std::string, std::string> &getSuperOptions() const;
private:
dev_t device;
int mount_id, parent_id;
std::string root, mount_point, optional_fields, filesystem_type, mount_source;
std::unordered_map<std::string, std::string> mount_options, super_options;
};
const std::vector<mountinfo_entry> &parseSelfMountinfo(bool cached = true);
class mountinfo_root_resolver
{
public:
mountinfo_root_resolver(const std::vector<mountinfo_entry> &mount_infos);
std::string resolveRootOf(const mountinfo_entry &mount_info) const;
private:
std::unordered_map<dev_t, std::string> device_mount_map;
};
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include <string>
#include <errno.h>
#include <functional>
#include "logging.hpp"
#include "zygisk.hpp"
#include "mountinfo_parser.hpp"
#define DCL_HOOK_FUNC(ret, func, ...) \
ret (*old_##func)(__VA_ARGS__) = nullptr; \
ret new_##func(__VA_ARGS__)
#define ASSERT_LOG(tag, expr) \
if (!(expr)) \
{ \
LOGE("%s:%d Assertion %s failed. %d:%s", #tag, __LINE__, #expr, errno, std::strerror(errno)); \
}
#define ASSERT_DO(tag, expr, ret) \
if (!(expr)) \
{ \
LOGE("%s:%d Assertion %s failed. %d:%s", #tag, __LINE__, #expr, errno, std::strerror(errno)); \
ret; \
}
namespace Utils
{
/*
* Always null terminates dest if dest_size is at least 1.
* Writes at most dest_size bytes to dest including null terminator.
* Reads at most dest_size bytes from src.
* Returns strlen(dest)
*/
size_t safeStringCopy(char *dest, const char *src, size_t dest_size);
bool switchMountNS(int pid);
int isUserAppUID(int uid);
bool hookPLTByName(zygisk::Api *api, const std::string &libName, const std::string &symbolName, void *hookFunc, void **origFunc);
int forkAndInvoke(const std::function<int()> &lambda);
const char *getExtErrorsBehavior(const Parsers::mountinfo_entry &entry);
}

1
module/jni/libcxx Submodule

Submodule module/jni/libcxx added at d5117df3ba

View File

@@ -1,89 +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_AFTER_CXX11',
'_LIBCPP_CONSTEXPR_AFTER_CXX14',
'_LIBCPP_CONSTEXPR_AFTER_CXX17',
'_LIBCPP_CONSTEXPR_AFTER_CXX20',
'_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
NamespaceIndentation: Inner
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

View File

@@ -1,60 +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,
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-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: __
# 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,
# modernize-use-override,
# 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,
# readability-simplify-boolean-expr,

View File

@@ -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/

View File

@@ -1,113 +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 \
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)

View File

@@ -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()

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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++

View File

@@ -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

View File

@@ -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

View File

@@ -1,230 +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
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
map.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()

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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 &
// ExperienceVolume 29 Issue 4 April 10, 1999 pp 341344.
// 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

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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 . Veri soƿet euripīðis id has,
sumo paulō dissentias duo , dētrāxīt neglēgeƿtur 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ī apēriæm fierent peÞentīūm. Eæm officiīs reprehēndunt .
Ut vel quodsī contentioƿes, his 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 . prō ǽmēt elit periculæ. Has virīs viderer ān.
Mel in suās pericūlīs āppellantur, nonumes deserūƿt ǽðversarium has. ĒliÞ
possīt commuƿe no ē, niȝh aċcusāmūs volūpÞatum no mel, ut quō ciȝo ðiceret.
Inǣni scripta quālīsque qūi, ad ipsūm persecuÞi mediōcritæÞēm vel.
Ǣppetere definitiōnes mel id. Leġerē āliquip nam , rēgione viderer pǣtrioque
duo te, meƿāƿdri prodēsseÞ ex hīs. Solum quidam 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 . Ēssent rætionibus 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 ēā,
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 ōð
cīvībūs.
Ēæ nibh æccommodarē eum. Ne etiæm īudico dicunt duo, quo tēmpor populo insōlens
. Ēos ē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, 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悩益そラとへ総始りゃほえ都多す田瀬シハナ終者ふくしン横梨せらげま雪爽かょルに松優個ムソヲ雑召喝塊媒ぶ。
20802
8稿9230稿388
宿78姿11895
姿476589
74429345姿
)");
}
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

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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();

View File

@@ -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()

View File

@@ -1,180 +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 library named <target> of the given <kind> (SHARED|STATIC).
# It imports a library named <name> searched at the given <path>.
function(imported_library target kind path name)
add_library(${target} ${kind} IMPORTED GLOBAL)
set(libnames "${CMAKE_${kind}_LIBRARY_PREFIX}${name}${CMAKE_${kind}_LIBRARY_SUFFIX}")
# Make sure we find .tbd files on macOS
if (kind STREQUAL "SHARED")
list(APPEND libnames "${CMAKE_${kind}_LIBRARY_PREFIX}${name}.tbd")
endif()
find_library(file
NAMES ${libnames}
PATHS "${path}"
NO_CACHE)
set_target_properties(${target} PROPERTIES IMPORTED_LOCATION "${file}")
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__")
imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" stdc++)
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
imported_library(libcxx-abi-static 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__")
imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" supc++)
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
imported_library(libcxx-abi-static 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")
imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" c++abi)
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
imported_library(libcxx-abi-static 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")
imported_library(libcxx-abi-shared SHARED "${LIBCXX_CXX_ABI_LIBRARY_PATH}" cxxrt)
target_link_libraries(libcxx-abi-shared INTERFACE libcxx-abi-headers)
imported_library(libcxx-abi-static 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()

View File

@@ -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()

View File

@@ -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 )

View File

@@ -1,2 +0,0 @@
set(LIBCXXABI_USE_LLVM_UNWINDER ON CACHE BOOL "")
set(CMAKE_CXX_COMPILER_TARGET "aarch64-linux-gnu" CACHE STRING "")

View File

@@ -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 "")

View File

@@ -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 "")

View File

@@ -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 "")

View File

@@ -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 "")

View File

@@ -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 "")

View File

@@ -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 "")

View File

@@ -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 "")

View File

@@ -1 +0,0 @@
set(LIBCXX_ABI_UNSTABLE ON CACHE BOOL "")

View File

@@ -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 "")

View File

@@ -1,2 +0,0 @@
set(LIBCXX_ENABLE_ASSERTIONS ON CACHE BOOL "")
set(LIBCXXABI_ENABLE_ASSERTIONS ON CACHE BOOL "")

View File

@@ -1,2 +0,0 @@
set(LIBCXX_TEST_PARAMS "std=c++03" CACHE STRING "")
set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")

Some files were not shown because too many files have changed in this diff Show More