From c84aae8f1bfefa56729efb72681a4345e921e15c Mon Sep 17 00:00:00 2001 From: Andrew Hopkins Date: Tue, 16 Feb 2021 09:29:56 -0800 Subject: [PATCH] Add CMake config to build benchmarks (#2582) * Fix some minor issues in existing benchmarks * Use feature probing for __restrict__ --- CMakeLists.txt | 34 +++++++++++++++++++++++++ s2n.mk | 6 +++++ tests/benchmark/s2n_base64_benchmark.cc | 2 +- tests/features/__restrict__.c | 27 ++++++++++++++++++++ utils/s2n_ensure.h | 16 ++++++++++++ 5 files changed, 84 insertions(+), 1 deletion(-) mode change 100755 => 100644 CMakeLists.txt create mode 100644 tests/features/__restrict__.c diff --git a/CMakeLists.txt b/CMakeLists.txt old mode 100755 new mode 100644 index 6332d9ed25d..8f0a7de0a2b --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,14 @@ try_compile( COMPILE_DEFINITIONS "-Werror" ) +# Determine if __restrict__ is available +try_compile( + __RESTRICT__SUPPORTED + ${CMAKE_BINARY_DIR} + SOURCES "${CMAKE_CURRENT_LIST_DIR}/tests/features/__restrict__.c" + COMPILE_DEFINITIONS "-Werror" +) + if(APPLE) set(OS_LIBS c Threads::Threads) elseif(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") @@ -229,6 +237,10 @@ if (FALL_THROUGH_SUPPORTED) target_compile_options(${PROJECT_NAME} PUBLIC -DS2N_FALL_THROUGH_SUPPORTED) endif() +if (__RESTRICT__SUPPORTED) + target_compile_options(${PROJECT_NAME} PUBLIC -DS2N___RESTRICT__SUPPORTED) +endif() + set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) find_package(LibCrypto REQUIRED) @@ -293,8 +305,30 @@ if (BUILD_TESTING) target_include_directories(s2nd PRIVATE $) target_include_directories(s2nd PRIVATE api) target_compile_options(s2nd PRIVATE -std=gnu99 -D_POSIX_C_SOURCE=200112L) + + if(BENCHMARK) + find_package(benchmark REQUIRED) + file(GLOB BENCHMARK_SRC "tests/benchmark/*.cc") + enable_language(CXX) + foreach(benchmark ${BENCHMARK_SRC}) + string(REGEX REPLACE ".+\\/(.+)\\.cc" "\\1" benchmark_name ${benchmark}) + add_executable(${benchmark_name} ${benchmark}) + target_include_directories(${benchmark_name} PRIVATE api) + target_include_directories(${benchmark_name} PRIVATE tests) + target_link_libraries(${benchmark_name} PUBLIC ${PROJECT_NAME} testss2n benchmark::benchmark) + + # Based off the flags in tests/benchmark/Makefile + target_compile_options(${benchmark_name} PRIVATE -pedantic -Wall -Werror -Wunused -Wcomment -Wchar-subscripts + -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings -Wno-deprecated-declarations + -Wno-unknown-pragmas -Wformat-security -Wno-missing-braces -fvisibility=hidden -Wno-unreachable-code + -Wno-unused-but-set-variable) + endforeach(benchmark) + + endif() endif() + + #install the s2n files install(FILES ${API_HEADERS} DESTINATION "include/" COMPONENT Development) diff --git a/s2n.mk b/s2n.mk index d2e10c3d875..41b141114f1 100644 --- a/s2n.mk +++ b/s2n.mk @@ -178,6 +178,12 @@ ifeq ($(TRY_COMPILE_FALL_THROUGH), 0) DEFAULT_CFLAGS += -DS2N_FALL_THROUGH_SUPPORTED endif +# Determine if __restrict__ is available +TRY_COMPILE__RESTRICT__ := $(call try_compile,$(S2N_ROOT)/tests/features/__restrict__.c) +ifeq ($(TRY_COMPILE__RESTRICT__), 0) + DEFAULT_CFLAGS += -DS2N___RESTRICT__SUPPORTED +endif + CFLAGS_LLVM = ${DEFAULT_CFLAGS} -emit-llvm -c -g -O1 $(BITCODE_DIR)%.bc: %.c diff --git a/tests/benchmark/s2n_base64_benchmark.cc b/tests/benchmark/s2n_base64_benchmark.cc index 16c397cb571..10e83b127c2 100644 --- a/tests/benchmark/s2n_base64_benchmark.cc +++ b/tests/benchmark/s2n_base64_benchmark.cc @@ -41,7 +41,7 @@ class TestFixture : public benchmark::Fixture { rc = s2n_blob_init(&r, pad.data(), pad.size()); assert(rc == 0); - result = s2n_get_urandom_data(&r); + result = s2n_get_public_random_data(&r); assert(s2n_result_is_ok(result)); rc = s2n_stuffer_alloc(&entropy, pad.size()); assert(rc == 0); diff --git a/tests/features/__restrict__.c b/tests/features/__restrict__.c new file mode 100644 index 00000000000..b29c32ef9ad --- /dev/null +++ b/tests/features/__restrict__.c @@ -0,0 +1,27 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0 + * + * or in the "license" file accompanying this file. This file 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. + */ + +void swap(int *__restrict__ left, int *__restrict__ right) { + int temp = *left; + *left = *right; + *right = temp; +} + +int main() { + int a = 1, b = 2; + swap(&a, &b); + return 0; +} + diff --git a/utils/s2n_ensure.h b/utils/s2n_ensure.h index 8949521e9a3..aee124b4201 100644 --- a/utils/s2n_ensure.h +++ b/utils/s2n_ensure.h @@ -67,4 +67,20 @@ } \ } while(0) +/** + * `restrict` is a part of the c99 standard and will work with any C compiler. If you're trying to + * compile with a C++ compiler `restrict` is invalid. However some C++ compilers support the behavior + * of `restrict` using the `__restrict__` keyword. Therefore if the compiler supports `__restrict__` + * use it. + * + * This is helpful for the benchmarks in tests/benchmark which use Google's Benchmark library and + * are all written in C++. + * + * https://gcc.gnu.org/onlinedocs/gcc/Restricted-Pointers.html + * + */ +#if defined(S2N___RESTRICT__SUPPORTED) +extern void* s2n_ensure_memcpy_trace(void *__restrict__ to, const void *__restrict__ from, size_t size, const char *debug_str); +#else extern void* s2n_ensure_memcpy_trace(void *restrict to, const void *restrict from, size_t size, const char *debug_str); +#endif