Skip to content

Commit 4c1d32b

Browse files
committed
Merge #36: A few improvements to prepare for subtree in Bitcoin Core
1e96b67 Improve MinGW building (Pieter Wuille) 67a67c2 Hide non-API library symbols (Pieter Wuille) 281f811 Add MSVC CountBits implementation using _BitScanReverse (Pieter Wuille) b21917d Work around clmul msan bug in clang < 11 (Pieter Wuille) 1261e9e CPUID support on MSVC (Pieter Wuille) ec49c07 A few fixes to prepare for MSVC building (Pieter Wuille) Pull request description: This includes various build system and compatibility improvements discovered in the process of subtreeing this into Bitcoin Core (see bitcoin/bitcoin#21859). * A few compatibility issues suggested [here](bitcoin/bitcoin#21859 (comment)) by sipsorcery. * Support for __builtin_clz equivalent on MSVC * Support for CPUID detection on MSVC * Prevent internal symbols from being exported * Make old MinGW CI work (-all-static instead of -static needed). ACKs for top commit: gmaxwell: utACK 1e96b67 (I also tested it, but not with mingw or msvc, so it doesn't count) Tree-SHA512: 83d457f39940ba9b6161a45181a8fb8853b793355eac61b7327f48c03e4261fadf06e7b05668e2f138236e520530ec2fd5ddff68afeccad3e4a3d3f184c5e25e
2 parents 20a8529 + 1e96b67 commit 4c1d32b

File tree

8 files changed

+167
-32
lines changed

8 files changed

+167
-32
lines changed

.cirrus.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,6 @@ task:
146146
env:
147147
EXEC_CMD: wine
148148
HOST: x86_64-w64-mingw32
149-
CXXFLAGS: -O2 -static -static-libgcc -static-libstdc++
150149
BUILD:
151150
<< : *MERGE_BASE
152151
test_script:

Makefile.am

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,19 +65,17 @@ endif
6565
bench_SOURCES = $(MINISKETCH_BENCH_SOURCES_INT)
6666
bench_CPPFLAGS = $(AM_CPPFLAGS) $(RELEASE_DEFINES)
6767
bench_LDADD = $(LIBMINISKETCH)
68-
bench_LDFLAGS = $(AM_LDFLAGS) -static
68+
bench_LDFLAGS = $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
6969

7070
test_SOURCES = $(MINISKETCH_TEST_SOURCES_INT)
7171
test_CPPFLAGS = $(AM_CPPFLAGS) $(RELEASE_DEFINES)
72-
test_CXXFLAGS = $(AM_CXXFLAGS)
7372
test_LDADD = $(LIBMINISKETCH)
74-
test_LDFLAGS = $(AM_LDFLAGS) -static
73+
test_LDFLAGS = $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
7574

7675
test_verify_SOURCES = $(MINISKETCH_TEST_SOURCES_INT)
7776
test_verify_CPPFLAGS = $(AM_CPPFLAGS) $(VERIFY_DEFINES)
78-
test_verify_CXXFLAGS = $(AM_CXXFLAGS)
7977
test_verify_LDADD = $(LIBMINISKETCH_VERIFY)
80-
test_verify_LDFLAGS = $(AM_LDFLAGS) -static
78+
test_verify_LDFLAGS = $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
8179

8280
EXTRA_DIST=
8381
EXTRA_DIST += LICENSE

build-aux/m4/ax_check_link_flag.m4

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# ===========================================================================
2+
# https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
3+
# ===========================================================================
4+
#
5+
# SYNOPSIS
6+
#
7+
# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
8+
#
9+
# DESCRIPTION
10+
#
11+
# Check whether the given FLAG works with the linker or gives an error.
12+
# (Warnings, however, are ignored)
13+
#
14+
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
15+
# success/failure.
16+
#
17+
# If EXTRA-FLAGS is defined, it is added to the linker's default flags
18+
# when the check is done. The check is thus made with the flags: "LDFLAGS
19+
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
20+
# issue an error when a bad flag is given.
21+
#
22+
# INPUT gives an alternative input source to AC_LINK_IFELSE.
23+
#
24+
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
25+
# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
26+
#
27+
# LICENSE
28+
#
29+
# Copyright (c) 2008 Guido U. Draheim <[email protected]>
30+
# Copyright (c) 2011 Maarten Bosmans <[email protected]>
31+
#
32+
# Copying and distribution of this file, with or without modification, are
33+
# permitted in any medium without royalty provided the copyright notice
34+
# and this notice are preserved. This file is offered as-is, without any
35+
# warranty.
36+
37+
#serial 6
38+
39+
AC_DEFUN([AX_CHECK_LINK_FLAG],
40+
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
41+
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
42+
AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
43+
ax_check_save_flags=$LDFLAGS
44+
LDFLAGS="$LDFLAGS $4 $1"
45+
AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
46+
[AS_VAR_SET(CACHEVAR,[yes])],
47+
[AS_VAR_SET(CACHEVAR,[no])])
48+
LDFLAGS=$ax_check_save_flags])
49+
AS_VAR_IF(CACHEVAR,yes,
50+
[m4_default([$2], :)],
51+
[m4_default([$3], :)])
52+
AS_VAR_POPDEF([CACHEVAR])dnl
53+
])dnl AX_CHECK_LINK_FLAGS

configure.ac

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ AC_LANG([C++])
1414

1515
AC_PATH_PROG(CCACHE,ccache)
1616

17+
saved_CXXFLAGS="$CXXFLAGS"
18+
CXXFLAGS="-fvisibility=hidden $CXXFLAGS"
19+
AC_MSG_CHECKING([if ${CXX} supports -fvisibility=hidden])
20+
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[char foo;]])],
21+
[ AC_MSG_RESULT([yes]) ],
22+
[ AC_MSG_RESULT([no])
23+
CXXFLAGS="$saved_CXXFLAGS"
24+
])
25+
1726
AC_ARG_ENABLE([ccache],
1827
[AS_HELP_STRING([--disable-ccache],
1928
[do not use ccache for building (default is to use if found)])],
@@ -88,6 +97,19 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [
8897
]
8998
)
9099

100+
AX_CHECK_LINK_FLAG([[-Wl,--exclude-libs,ALL]],[LDFLAGS="-Wl,--exclude-libs,ALL $LDFLAGS"])
101+
102+
case $host in
103+
*mingw*)
104+
dnl -static is interpreted by libtool, where it has a different meaning.
105+
dnl In libtool-speak, it's -all-static.
106+
AX_CHECK_LINK_FLAG([[-static]],[LIBTOOL_APP_LDFLAGS="$LIBTOOL_APP_LDFLAGS -all-static"])
107+
;;
108+
*)
109+
AX_CHECK_LINK_FLAG([[-static]],[LIBTOOL_APP_LDFLAGS="-static"])
110+
;;
111+
esac
112+
91113
AX_CHECK_COMPILE_FLAG([-Wall],[WARN_CXXFLAGS="$WARN_CXXFLAGS -Wall"],,[[$CXXFLAG_WERROR]])
92114
## Some compilers (gcc) ignore unknown -Wno-* options, but warn about all
93115
## unknown options if any other warning is produced. Test the -Wfoo case, and
@@ -125,6 +147,7 @@ AC_SUBST(WARN_CXXFLAGS)
125147
AC_SUBST(NOWARN_CXXFLAGS)
126148
AC_SUBST(VERIFY_DEFINES)
127149
AC_SUBST(RELEASE_DEFINES)
150+
AC_SUBST(LIBTOOL_APP_LDFLAGS)
128151
AM_CONDITIONAL([ENABLE_CLMUL],[test x$enable_clmul = xyes])
129152
AM_CONDITIONAL([USE_BENCHMARK], [test x"$use_benchmark" = x"yes"])
130153
AM_CONDITIONAL([USE_TESTS], [test x"$use_tests" != x"no"])

include/minisketch.h

Lines changed: 38 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,26 @@
33

44
#include <stdint.h>
55
#include <stdlib.h>
6-
#include <unistd.h>
6+
7+
#ifdef _MSC_VER
8+
# include <compat.h>
9+
#else
10+
# include <unistd.h>
11+
#endif
12+
13+
#ifndef MINISKETCH_API
14+
# if defined(_WIN32)
15+
# ifdef MINISKETCH_BUILD
16+
# define MINISKETCH_API __declspec(dllexport)
17+
# else
18+
# define MINISKETCH_API
19+
# endif
20+
# elif defined(__GNUC__) && (__GNUC__ >= 4) && defined(MINISKETCH_BUILD)
21+
# define MINISKETCH_API __attribute__ ((visibility ("default")))
22+
# else
23+
# define MINISKETCH_API
24+
# endif
25+
#endif
726

827
#ifdef __cplusplus
928
# if __cplusplus >= 201103L
@@ -21,7 +40,7 @@ extern "C" {
2140
typedef struct minisketch minisketch;
2241

2342
/** Determine whether support for elements of `bits` bits was compiled in. */
24-
int minisketch_bits_supported(uint32_t bits);
43+
MINISKETCH_API int minisketch_bits_supported(uint32_t bits);
2544

2645
/** Determine the maximum number of implementations available.
2746
*
@@ -32,13 +51,13 @@ int minisketch_bits_supported(uint32_t bits);
3251
* function call, inclusive. Note that not every combination of implementation
3352
* and element size may exist (see further).
3453
*/
35-
uint32_t minisketch_implementation_max(void);
54+
MINISKETCH_API uint32_t minisketch_implementation_max(void);
3655

3756
/** Determine if the a combination of bits and implementation number is available.
3857
*
3958
* Returns 1 if it is, 0 otherwise.
4059
*/
41-
int minisketch_implementation_supported(uint32_t bits, uint32_t implementation);
60+
MINISKETCH_API int minisketch_implementation_supported(uint32_t bits, uint32_t implementation);
4261

4362
/** Construct a sketch for a given element size, implementation and capacity.
4463
*
@@ -49,16 +68,16 @@ int minisketch_implementation_supported(uint32_t bits, uint32_t implementation);
4968
*
5069
* If the result is not NULL, it must be destroyed using minisketch_destroy.
5170
*/
52-
minisketch* minisketch_create(uint32_t bits, uint32_t implementation, size_t capacity);
71+
MINISKETCH_API minisketch* minisketch_create(uint32_t bits, uint32_t implementation, size_t capacity);
5372

5473
/** Get the element size of a sketch in bits. */
55-
uint32_t minisketch_bits(const minisketch* sketch);
74+
MINISKETCH_API uint32_t minisketch_bits(const minisketch* sketch);
5675

5776
/** Get the capacity of a sketch. */
58-
size_t minisketch_capacity(const minisketch* sketch);
77+
MINISKETCH_API size_t minisketch_capacity(const minisketch* sketch);
5978

6079
/** Get the implementation of a sketch. */
61-
uint32_t minisketch_implementation(const minisketch* sketch);
80+
MINISKETCH_API uint32_t minisketch_implementation(const minisketch* sketch);
6281

6382
/** Set the seed for randomizing algorithm choices to a fixed value.
6483
*
@@ -71,28 +90,28 @@ uint32_t minisketch_implementation(const minisketch* sketch);
7190
* When seed is -1, a fixed internal value with predictable behavior is
7291
* used. It is only intended for testing.
7392
*/
74-
void minisketch_set_seed(minisketch* sketch, uint64_t seed);
93+
MINISKETCH_API void minisketch_set_seed(minisketch* sketch, uint64_t seed);
7594

7695
/** Clone a sketch.
7796
*
7897
* The result must be destroyed using minisketch_destroy.
7998
*/
80-
minisketch* minisketch_clone(const minisketch* sketch);
99+
MINISKETCH_API minisketch* minisketch_clone(const minisketch* sketch);
81100

82101
/** Destroy a sketch.
83102
*
84103
* The pointer that was passed in may not be used anymore afterwards.
85104
*/
86-
void minisketch_destroy(minisketch* sketch);
105+
MINISKETCH_API void minisketch_destroy(minisketch* sketch);
87106

88107
/** Compute the size in bytes for serializing a given sketch. */
89-
size_t minisketch_serialized_size(const minisketch* sketch);
108+
MINISKETCH_API size_t minisketch_serialized_size(const minisketch* sketch);
90109

91110
/** Serialize a sketch to bytes. */
92-
void minisketch_serialize(const minisketch* sketch, unsigned char* output);
111+
MINISKETCH_API void minisketch_serialize(const minisketch* sketch, unsigned char* output);
93112

94113
/** Deserialize a sketch from bytes. */
95-
void minisketch_deserialize(minisketch* sketch, const unsigned char* input);
114+
MINISKETCH_API void minisketch_deserialize(minisketch* sketch, const unsigned char* input);
96115

97116
/** Add an element to a sketch.
98117
*
@@ -107,7 +126,7 @@ void minisketch_deserialize(minisketch* sketch, const unsigned char* input);
107126
*
108127
* Note that adding the same element a second time removes it again.
109128
*/
110-
void minisketch_add_uint64(minisketch* sketch, uint64_t element);
129+
MINISKETCH_API void minisketch_add_uint64(minisketch* sketch, uint64_t element);
111130

112131
/** Merge the elements of another sketch into this sketch.
113132
*
@@ -125,7 +144,7 @@ void minisketch_add_uint64(minisketch* sketch, uint64_t element);
125144
* of two sketches with the same element size and capacity by performing a bitwise XOR
126145
* of the serializations.
127146
*/
128-
size_t minisketch_merge(minisketch* sketch, const minisketch* other_sketch);
147+
MINISKETCH_API size_t minisketch_merge(minisketch* sketch, const minisketch* other_sketch);
129148

130149
/** Decode a sketch.
131150
*
@@ -134,7 +153,7 @@ size_t minisketch_merge(minisketch* sketch, const minisketch* other_sketch);
134153
*
135154
* The return value is the number of decoded elements, or -1 if decoding failed.
136155
*/
137-
ssize_t minisketch_decode(const minisketch* sketch, size_t max_elements, uint64_t* output);
156+
MINISKETCH_API ssize_t minisketch_decode(const minisketch* sketch, size_t max_elements, uint64_t* output);
138157

139158
/** Compute the capacity needed to achieve a certain rate of false positives.
140159
*
@@ -148,7 +167,7 @@ ssize_t minisketch_decode(const minisketch* sketch, size_t max_elements, uint64_
148167
* function computes the necessary capacity. It is only guaranteed to be
149168
* accurate up to fpbits=256.
150169
*/
151-
size_t minisketch_compute_capacity(uint32_t bits, size_t max_elements, uint32_t fpbits);
170+
MINISKETCH_API size_t minisketch_compute_capacity(uint32_t bits, size_t max_elements, uint32_t fpbits);
152171

153172
/** Compute what max_elements can be decoded for a certain rate of false positives.
154173
*
@@ -166,7 +185,7 @@ size_t minisketch_compute_capacity(uint32_t bits, size_t max_elements, uint32_t
166185
* chance of 1 in 2^18.5). Therefore, minisketch_compute_max_elements with
167186
* capacity=9 will return 9.
168187
*/
169-
size_t minisketch_compute_max_elements(uint32_t bits, size_t capacity, uint32_t fpbits);
188+
MINISKETCH_API size_t minisketch_compute_max_elements(uint32_t bits, size_t capacity, uint32_t fpbits);
170189

171190
#ifdef __cplusplus
172191
}

src/fields/clmul_common_impl.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,27 @@
88
#define _MINISKETCH_FIELDS_CLMUL_COMMON_IMPL_H_ 1
99

1010
#include <stdint.h>
11-
#include <x86intrin.h>
11+
#include <immintrin.h>
1212

1313
#include "../int_utils.h"
1414
#include "../lintrans.h"
1515

1616
namespace {
1717

18-
template<typename I, int BITS, I MOD> I MulWithClMulReduce(I a, I b)
18+
// The memory sanitizer in clang < 11 cannot reason through _mm_clmulepi64_si128 calls.
19+
// Disable memory sanitization in the functions using them for those compilers.
20+
#if defined(__clang__) && (__clang_major__ < 11)
21+
# if defined(__has_feature)
22+
# if __has_feature(memory_sanitizer)
23+
# define NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory")))
24+
# endif
25+
# endif
26+
#endif
27+
#ifndef NO_SANITIZE_MEMORY
28+
# define NO_SANITIZE_MEMORY
29+
#endif
30+
31+
template<typename I, int BITS, I MOD> NO_SANITIZE_MEMORY I MulWithClMulReduce(I a, I b)
1932
{
2033
static constexpr I MASK = Mask<BITS, I>();
2134

@@ -52,7 +65,7 @@ template<typename I, int BITS, I MOD> I MulWithClMulReduce(I a, I b)
5265
}
5366
}
5467

55-
template<typename I, int BITS, int POS> I MulTrinomial(I a, I b)
68+
template<typename I, int BITS, int POS> NO_SANITIZE_MEMORY I MulTrinomial(I a, I b)
5669
{
5770
static constexpr I MASK = Mask<BITS, I>();
5871

src/int_utils.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include <algorithm>
1414
#include <type_traits>
1515

16+
#ifdef _MSC_VER
17+
# include <intrin.h>
18+
#endif
19+
1620
template<int bits>
1721
static constexpr inline uint64_t Rot(uint64_t x) { return (x << bits) | (x >> (64 - bits)); }
1822

@@ -135,6 +139,17 @@ static inline int CountBits(I val, int max) {
135139
} else {
136140
return std::numeric_limits<unsigned long long>::digits - __builtin_clzll(val);
137141
}
142+
#elif _MSC_VER
143+
(void)max;
144+
unsigned long index;
145+
unsigned char ret;
146+
if (std::numeric_limits<I>::digits <= 32) {
147+
ret = _BitScanReverse(&index, val);
148+
} else {
149+
ret = _BitScanReverse64(&index, val);
150+
}
151+
if (!ret) return 0;
152+
return index;
138153
#else
139154
while (max && (val >> (max - 1) == 0)) --max;
140155
return max;

0 commit comments

Comments
 (0)