Provides support for clang under Windows. (#817)

This commit is contained in:
Daniel Lemire 2020-04-27 19:09:27 -07:00 committed by GitHub
parent 04e47bde84
commit 2a1f8fa8f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 438 additions and 194 deletions

View File

@ -8,6 +8,8 @@ environment:
matrix:
- job_name: VS2019
CMAKE_ARGS: -DSIMDJSON_CHECKPERF_BRANCH=jkeiser/parse-t
- job_name: VS2019CLANG
CMAKE_ARGS: -T ClangCL
- job_name: VS2017 (Static, No Threads)
image: Visual Studio 2017
CMAKE_ARGS: -DSIMDJSON_BUILD_STATIC=ON -DSIMDJSON_ENABLE_THREADS=OFF
@ -30,5 +32,6 @@ test_script:
- ctest --output-on-failure -C %Configuration% --verbose %CTEST_ARGS% --parallel
clone_folder: c:\projects\simdjson
matrix:
fast_finish: true

View File

@ -64,6 +64,53 @@ While simdjson distributes just two files from the singleheader/ directory, we *
multiple files under include/ and src/. include/simdjson.h and src/simdjson.cpp are the "spine" for
these, and you can include
Runtime Dispatching
--------------------
A key feature of simdjson is the ability to compile different processing kernels, optimized for specific instruction sets, and to select
the most appropriate kernel at runtime. This ensures that users get the very best performance while still enabling simdjson to run everywhere.
This technique is frequently called runtime dispatching. The simdjson achieves runtime dispatching entirely in C++: we do not assume
that the user is building the code using CMake, for example.
To make runtime dispatching work, it is critical that the code be compiled for the lowest supported processor. In particular, you should
not use flags such as -mavx2, /arch:AVX2 and so forth while compiling simdjson. When you do so, you allow the compiler to use advanced
instructions. In turn, these advanced instructions present in the code may cause a runtime failure if the runtime processor does not
support them. Even a simple loop, compiled with these flags, might generate binary code that only run on advanced processors.
So we compile simdjson for a generic processor. Our users should do the same if they want simdjson's runtime dispatch to work. It is important
to understand that if runtime dispatching does not work, then simdjson will cause crashes on older processors. Of course, if a user chooses
to compile their code for a specific instruction set (e.g., AVX2), they are responsible for the failures if they later run their code
on a processor that does not support AVX2. Yet, if we were to entice these users to do so, we would share the blame: thus we carefully instruct
users to compile their code in a generic way without doing anything to enable advanced instructions.
We only use runtime dispatching on x64 (AMD/Intel) platforms, at the moment. On ARM processors, we would need a standard way to query, at runtime,
the processor for its supported features. We do not know how to do so on ARM systems in general. Thankfully it is not yet a concern: 64-bit ARM
processors are fairly uniform as far as the instruction sets they support.
In all cases, simdjson uses advanced instructions by relying on "intrinsic functions": we do not write assembly code. The intrinsic functions
are special functions that the compiler might recognize and translate into fast code. To make runtime dispatching work, we rely on the fact that
the header providing these instructions
(intrin.h under Visual Studio, x86intrin.h elsewhere) defines all of the intrinsic functions, including those that are not supported
processor.
At this point, we are require to use one of two main strategies.
1. On POSIX systems, the main compilers (LLVM clang, GNU gcc) allow us to use any intrinsic function after including the header, but they fail to inline the resulting instruction if the target processor does not support them. Because we compile for a generic processor, we would not be able to use most intrinsic functions. Thankfully, more recent versions of these compilers allow us to flag a region of code with a specific target, so that we can compile only some of the code with support for advanced instructions. Thus in our C++, one might notice macros like `TARGET_HASWELL`. It is then our responsability, at runtime, to only run the regions of code (that we call kernels) matching the properties of the runtime processor. The benefit of this approach is that the compiler not only let us use intrinsic functions, but it can also optimize the rest of the code in the kernel with advanced instructions we enabled.
2. Under Visual Studio, the problem is somewhat simpler. Visual Studio will not only provide the intrinsic functions, but it will also allow us to use them. They will compile just fine. It is at runtime that they may cause a crash. So we do not need to mark regions of code for compilation toward advanced processors (e.g., with `TARGET_HASWELL` macros). The downside of the Visual Studio approach is that the compiler is not allowed to use advanced instructions others than those we specify. In principle, this means that Visual Studio has weaker optimization opportunities.
We also handle the special case where a user is compiling using LLVM clang under Windows, [using the Visual Studio toolchain](https://devblogs.microsoft.com/cppblog/clang-llvm-support-in-visual-studio/). If you compile with LLVM clang under Visual Studio, then the header files (intrin.h or x86intrin.h) no longer provides the intrinsic functions that are unsupported by the processor. This appears to be deliberate on the part of the LLVM engineers. With a few lines of code, we handle this scenario just like LLVM clang under a POSIX system, but forcing the inclusion of the specific headers, and rolling our own intrinsic function as needed.
Regenerating Single Headers From Master
---------------------------------------
@ -103,7 +150,7 @@ pkg install bash
pkg install cmake
```
You need a recent compiler like clang or gcc. We recommend at least GNU GCC/G++ 7 or LLVM clang 6.
You need a recent compiler like clang or gcc. We recommend at least GNU GCC/G++ 7 or LLVM clang 6.
Building: While in the project repository, do the following:
@ -153,10 +200,28 @@ We assume you have a common 64-bit Windows PC with at least Visual Studio 2017 a
- Grab the simdjson code from GitHub, e.g., by cloning it using [GitHub Desktop](https://desktop.github.com/).
- Install [CMake](https://cmake.org/download/). When you install it, make sure to ask that `cmake` be made available from the command line. Please choose a recent version of cmake.
- Create a subdirectory within simdjson, such as `VisualStudio`.
- Using a shell, go to this newly created directory. You can start a shell directly from GitHub Desktop (Repository > Open in Command Prompt).
- Using a shell, go to this newly created directory. You can start a shell directly from GitHub Desktop (Repository > Open in Command Prompt).
- Type `cmake -DCMAKE_GENERATOR_PLATFORM=x64 ..` in the shell while in the `VisualStudio` repository. (Alternatively, if you want to build a DLL, you may use the command line `cmake -DCMAKE_GENERATOR_PLATFORM=x64 -DSIMDJSON_BUILD_STATIC=OFF ..`.)
- This last command (`cmake ...`) created a Visual Studio solution file in the newly created directory (e.g., `simdjson.sln`). Open this file in Visual Studio. You should now be able to build the project and run the tests. For example, in the `Solution Explorer` window (available from the `View` menu), right-click `ALL_BUILD` and select `Build`. To test the code, still in the `Solution Explorer` window, select `RUN_TESTS` and select `Build`.
Though having Visual Studio installed is necessary, one can build simdjson using only cmake commands:
- `mkdir build`
- `cd build`
- `cmake ..`
- `cmake --build . -config Release`
Furthermore, if you have installed LLVM clang on Windows, for example as a component of Visual Studio 2019, you can configure and build simdjson using LLVM clang on Windows using cmake:
- `mkdir build`
- `cd build`
- `cmake .. -T ClangCL`
- `cmake --build . -config Release`
### Usage (Using `vcpkg` on 64-bit Windows, Linux and macOS)
[vcpkg](https://github.com/Microsoft/vcpkg) users on Windows, Linux and macOS can download and install `simdjson` with one single command from their favorite shell.

View File

@ -19,9 +19,8 @@ An overview of what you need to know to use simdjson, with examples.
Requirements
------------------
- A recent compiler (LLVM clang6 or better, GNU GCC 7 or better, Visual Studio 2017 or better). We require C++11 support as a minimum.
- A 64-bit system (ARM or x64 Intel/AMD). We run tests on macOS, freeBSD, Linux and Windows. We recommend that Visual Studio users target a 64-bit build (x64) instead of a 32-bit build (x86).
- A recent compiler (LLVM clang6 or better, GNU GCC 7 or better) on a 64-bit (ARM or x64 Intel/AMD) POSIX systems such as macOS, freeBSD or Linux. We require that the compiler supports the C++11 standard or better.
- Visual Studio 2017 or better under 64-bit Windows. Users should target a 64-bit build (x64) instead of a 32-bit build (x86). We support the LLVM clang compiler under Visual Studio (clangcl) as well as as the regular Visual Studio compiler.
Including simdjson
------------------

View File

@ -47,9 +47,12 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
#define DEBUG_BLOCK(name, block)
#endif
#if !defined(_MSC_VER) && !defined(SIMDJSON_NO_COMPUTED_GOTO)
#if !defined(SIMDJSON_REGULAR_VISUAL_STUDIO) && !defined(SIMDJSON_NO_COMPUTED_GOTO)
// We assume here that *only* regular visual studio
// does not support computed gotos.
// Implemented using Labels as Values which works in GCC and CLANG (and maybe
// also in Intel's compiler), but won't work in MSVC.
// Compute gotos are good for performance, enable them if you can.
#define SIMDJSON_USE_COMPUTED_GOTO
#endif
@ -59,7 +62,7 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
#define ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n)-1)) == 0)
#if defined(_MSC_VER) && !defined(__clang__)
#if defined(SIMDJSON_REGULAR_VISUAL_STUDIO)
#define really_inline __forceinline
#define never_inline __declspec(noinline)
@ -80,13 +83,7 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
#define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_VS_WARNING(4996)
#define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop ))
#if SIMDJSON_USING_LIBRARY
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport)
#else
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllexport)
#endif
#else // MSC_VER
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
#define really_inline inline __attribute__((always_inline, unused))
#define never_inline inline __attribute__((noinline, unused))
@ -119,19 +116,24 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
#define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wdeprecated-declarations)
#define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop")
#if defined(_MSC_VER) && defined(__clang__)
#endif // MSC_VER
#if defined(SIMDJSON_VISUAL_STUDIO)
/**
* It does not matter here whether you are using
* the regular visual studio or clang under visual
* studio.
*/
#if SIMDJSON_USING_LIBRARY
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport)
#else
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllexport)
#endif
#else
#else
#define SIMDJSON_DLLIMPORTEXPORT
#endif
#endif // MSC_VER
#endif
// C++17 requires string_view.
#if SIMDJSON_CPLUSPLUS17

View File

@ -4,19 +4,46 @@
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#ifdef _MSC_VER
#define SIMDJSON_VISUAL_STUDIO 1
/**
* We want to differentiate carefully between
* clang under visual studio and regular visual
* studio.
*
* Under clang for Windows, we enable:
* * target pragmas so that part and only part of the
* code gets compiled for advanced instructions.
* * computed gotos.
*
*/
#ifdef __clang__
// clang under visual studio
#define SIMDJSON_CLANG_VISUAL_STUDIO 1
#else
// just regular visual studio (best guess)
#define SIMDJSON_REGULAR_VISUAL_STUDIO 1
#endif // __clang__
#endif // _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
// https://en.wikipedia.org/wiki/C_alternative_tokens
// This header should have no effect, except maybe
// under Visual Studio.
#include <iso646.h>
#endif
#if defined(__x86_64__) || defined(_M_AMD64)
#define IS_X86_64 1
#define SIMDJSON_IS_X86_64 1
#endif
#if defined(__aarch64__) || defined(_M_ARM64)
#define IS_ARM64 1
#define SIMDJSON_IS_ARM64 1
#endif
#if (!defined(IS_X86_64)) && (!defined(IS_ARM64))
#if _MSC_VER
#if (!defined(SIMDJSON_IS_X86_64)) && (!defined(SIMDJSON_IS_ARM64))
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
#pragma message("The simdjson library is designed\
for 64-bit processors and it seems that you are not \
compiling for a known 64-bit platform. All fast kernels \
@ -27,7 +54,7 @@ use a 64-bit target such as x64 or 64-bit ARM.")
for 64-bit processors. It seems that you are not \
compiling for a known 64-bit platform."
#endif
#endif // (!defined(IS_X86_64)) && (!defined(IS_ARM64))
#endif // (!defined(SIMDJSON_IS_X86_64)) && (!defined(SIMDJSON_IS_ARM64))
// this is almost standard?
#undef STRINGIFY_IMPLEMENTATION_
@ -39,15 +66,15 @@ compiling for a known 64-bit platform."
#define SIMDJSON_IMPLEMENTATION_FALLBACK 1
#endif
#if IS_ARM64
#if SIMDJSON_IS_ARM64
#ifndef SIMDJSON_IMPLEMENTATION_ARM64
#define SIMDJSON_IMPLEMENTATION_ARM64 1
#endif
#define SIMDJSON_IMPLEMENTATION_HASWELL 0
#define SIMDJSON_IMPLEMENTATION_WESTMERE 0
#endif // IS_ARM64
#endif // SIMDJSON_IS_ARM64
#if IS_X86_64
#if SIMDJSON_IS_X86_64
#ifndef SIMDJSON_IMPLEMENTATION_HASWELL
#define SIMDJSON_IMPLEMENTATION_HASWELL 1
#endif
@ -55,10 +82,10 @@ compiling for a known 64-bit platform."
#define SIMDJSON_IMPLEMENTATION_WESTMERE 1
#endif
#define SIMDJSON_IMPLEMENTATION_ARM64 0
#endif // IS_X86_64
#endif // SIMDJSON_IS_X86_64
// we are going to use runtime dispatch
#ifdef IS_X86_64
#ifdef SIMDJSON_IS_X86_64
#ifdef __clang__
// clang does not have GCC push pop
// warning: clang attribute push can't be used within a namespace in clang up
@ -115,11 +142,10 @@ compiling for a known 64-bit platform."
#define NO_SANITIZE_UNDEFINED
#endif
#ifdef _MSC_VER
#include <intrin.h> // visual studio
#endif
#ifdef _MSC_VER
#ifdef SIMDJSON_VISUAL_STUDIO
// This is one case where we do not distinguish between
// regular visual studio and clang under visual studio.
// clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
#define simdjson_strcasecmp _stricmp
#else
#define simdjson_strcasecmp strcasecmp
@ -129,7 +155,7 @@ namespace simdjson {
/** @private portable version of posix_memalign */
static inline void *aligned_malloc(size_t alignment, size_t size) {
void *p;
#ifdef _MSC_VER
#ifdef SIMDJSON_VISUAL_STUDIO
p = _aligned_malloc(size, alignment);
#elif defined(__MINGW32__) || defined(__MINGW64__)
p = __mingw_aligned_malloc(size, alignment);
@ -153,7 +179,7 @@ static inline void aligned_free(void *mem_block) {
if (mem_block == nullptr) {
return;
}
#ifdef _MSC_VER
#ifdef SIMDJSON_VISUAL_STUDIO
_aligned_free(mem_block);
#elif defined(__MINGW32__) || defined(__MINGW64__)
__mingw_aligned_free(mem_block);

View File

@ -1,4 +1,4 @@
#!/bin/bash
#!/usr/bin/env bash
########################################################################
# Generates an "amalgamation build" for roaring. Inspired by similar
# script used by whefs.

View File

@ -1,4 +1,4 @@
/* auto-generated on Thu Apr 23 15:36:58 PDT 2020. Do not edit! */
/* auto-generated on Mon 27 Apr 2020 21:20:37 EDT. Do not edit! */
#include <iostream>
#include "simdjson.h"

View File

@ -1,12 +1,12 @@
/* auto-generated on Thu Apr 23 15:36:58 PDT 2020. Do not edit! */
/* auto-generated on Mon 27 Apr 2020 21:20:37 EDT. Do not edit! */
/* begin file simdjson.cpp */
#include "simdjson.h"
/* used for http://dmalloc.com/ Dmalloc - Debug Malloc Library */
#ifdef DMALLOC
#include "dmalloc.h"
#if defined(SIMDJSON_CLANG_VISUAL_STUDIO)
SIMDJSON_DISABLE_GCC_WARNING(-Wmicrosoft-include)
#endif
/* begin file simdjson.cpp */
/* begin file error.cpp */
namespace simdjson {
@ -17,7 +17,7 @@ namespace internal {
{ SUCCESS_AND_HAS_MORE, "No error and buffer still has more data" },
{ CAPACITY, "This parser can't support a document that big" },
{ MEMALLOC, "Error allocating memory, we're most likely out of memory" },
{ TAPE_ERROR, "Something went wrong while writing to the tape" },
{ TAPE_ERROR, "The JSON document has an improper structure: missing or superfluous commas, braces, missing keys, etc." },
{ DEPTH_ERROR, "The JSON document was too deep (too many nested objects and arrays)" },
{ STRING_ERROR, "Problem while parsing a string" },
{ T_ATOM_ERROR, "Problem while parsing an atom starting with the letter 't'" },
@ -659,15 +659,15 @@ namespace arm64 {
// Sadly, sanitizers are not smart enough to figure it out.
NO_SANITIZE_UNDEFINED
really_inline int trailing_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
unsigned long ret;
// Search the mask data from least significant bit (LSB)
// to the most significant bit (MSB) for a set bit (1).
_BitScanForward64(&ret, input_num);
return (int)ret;
#else // _MSC_VER
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
return __builtin_ctzll(input_num);
#endif // _MSC_VER
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
}
/* result might be undefined when input_num is zero */
@ -677,7 +677,7 @@ really_inline uint64_t clear_lowest_bit(uint64_t input_num) {
/* result might be undefined when input_num is zero */
really_inline int leading_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
unsigned long leading_zero = 0;
// Search the mask data from most significant bit (MSB)
// to least significant bit (LSB) for a set bit (1).
@ -687,7 +687,7 @@ really_inline int leading_zeroes(uint64_t input_num) {
return 64;
#else
return __builtin_clzll(input_num);
#endif// _MSC_VER
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
}
/* result might be undefined when input_num is zero */
@ -696,7 +696,7 @@ really_inline int count_ones(uint64_t input_num) {
}
really_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
*result = value1 + value2;
return *result < value1;
#else
@ -706,7 +706,7 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *resu
}
really_inline bool mul_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
*result = value1 * value2;
return !!__umulh(value1, value2);
#else
@ -2392,11 +2392,53 @@ WARN_UNUSED error_code implementation::minify(const uint8_t *buf, size_t len, ui
#define SIMDJSON_HASWELL_INTRINSICS_H
#ifdef _MSC_VER
#include <intrin.h> // visual studio
#ifdef SIMDJSON_VISUAL_STUDIO
// under clang within visual studio, this will include <x86intrin.h>
#include <intrin.h> // visual studio or clang
#else
#include <x86intrin.h> // elsewhere
#endif // _MSC_VER
#endif // SIMDJSON_VISUAL_STUDIO
#ifdef SIMDJSON_CLANG_VISUAL_STUDIO
/**
* You are not supposed, normally, to include these
* headers directly. Instead you should either include intrin.h
* or x86intrin.h. However, when compiling with clang
* under Windows (i.e., when _MSC_VER is set), these headers
* only get included *if* the corresponding features are detected
* from macros:
* e.g., if __AVX2__ is set... in turn, we normally set these
* macros by compiling against the corresponding architecture
* (e.g., arch:AVX2, -mavx2, etc.) which compiles the whole
* software with these advanced instructions. In simdjson, we
* want to compile the whole program for a generic target,
* and only target our specific kernels. As a workaround,
* we directly include the needed headers. These headers would
* normally guard against such usage, but we carefully included
* <x86intrin.h> (or <intrin.h>) before, so the headers
* are fooled.
*/
#include <bmiintrin.h> // for _blsr_u64
#include <lzcntintrin.h> // for __lzcnt64
#include <immintrin.h> // for most things (AVX2, AVX512, _popcnt64)
#include <smmintrin.h>
#include <tmmintrin.h>
#include <avxintrin.h>
#include <avx2intrin.h>
#include <wmmintrin.h> // for _mm_clmulepi64_si128
// unfortunately, we may not get _blsr_u64, but, thankfully, clang
// has it as a macro.
#ifndef _blsr_u64
// we roll our own
TARGET_HASWELL
static really_inline uint64_t simdjson_blsr_u64(uint64_t n) {
return (n - 1) & n;
}
UNTARGET_REGION
#define _blsr_u64(a) (simdjson_blsr_u64((a)))
#endif // _blsr_u64
#endif
#endif // SIMDJSON_HASWELL_INTRINSICS_H
/* end file */
@ -2446,16 +2488,16 @@ namespace haswell {
// Sadly, sanitizers are not smart enough to figure it out.
NO_SANITIZE_UNDEFINED
really_inline int trailing_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
return (int)_tzcnt_u64(input_num);
#else // _MSC_VER
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
////////
// You might expect the next line to be equivalent to
// return (int)_tzcnt_u64(input_num);
// but the generated code differs and might be less efficient?
////////
return __builtin_ctzll(input_num);
#endif // _MSC_VER
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
}
/* result might be undefined when input_num is zero */
@ -2468,7 +2510,7 @@ really_inline int leading_zeroes(uint64_t input_num) {
return int(_lzcnt_u64(input_num));
}
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
really_inline unsigned __int64 count_ones(uint64_t input_num) {
// note: we do not support legacy 32-bit Windows
return __popcnt64(input_num);// Visual Studio wants two underscores
@ -2481,7 +2523,7 @@ really_inline long long int count_ones(uint64_t input_num) {
really_inline bool add_overflow(uint64_t value1, uint64_t value2,
uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
return _addcarry_u64(0, value1, value2,
reinterpret_cast<unsigned __int64 *>(result));
#else
@ -2490,12 +2532,12 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2,
#endif
}
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
#pragma intrinsic(_umul128)
#endif
really_inline bool mul_overflow(uint64_t value1, uint64_t value2,
uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
uint64_t high;
*result = _umul128(value1, value2, &high);
return high;
@ -3935,11 +3977,28 @@ UNTARGET_REGION
#ifndef SIMDJSON_WESTMERE_INTRINSICS_H
#define SIMDJSON_WESTMERE_INTRINSICS_H
#ifdef _MSC_VER
#include <intrin.h> // visual studio
#ifdef SIMDJSON_VISUAL_STUDIO
// under clang within visual studio, this will include <x86intrin.h>
#include <intrin.h> // visual studio or clang
#else
#include <x86intrin.h> // elsewhere
#endif // _MSC_VER
#endif // SIMDJSON_VISUAL_STUDIO
#ifdef SIMDJSON_CLANG_VISUAL_STUDIO
/**
* You are not supposed, normally, to include these
* headers directly. Instead you should either include intrin.h
* or x86intrin.h. However, when compiling with clang
* under Windows (i.e., when _MSC_VER is set), these headers
* only get included *if* the corresponding features are detected
* from macros:
*/
#include <smmintrin.h> // for _mm_alignr_epi8
#include <wmmintrin.h> // for _mm_clmulepi64_si128
#endif
#endif // SIMDJSON_WESTMERE_INTRINSICS_H
/* end file */
@ -3988,15 +4047,15 @@ namespace westmere {
// Sadly, sanitizers are not smart enough to figure it out.
NO_SANITIZE_UNDEFINED
really_inline int trailing_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
unsigned long ret;
// Search the mask data from least significant bit (LSB)
// to the most significant bit (MSB) for a set bit (1).
_BitScanForward64(&ret, input_num);
return (int)ret;
#else // _MSC_VER
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
return __builtin_ctzll(input_num);
#endif // _MSC_VER
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
}
/* result might be undefined when input_num is zero */
@ -4006,7 +4065,7 @@ really_inline uint64_t clear_lowest_bit(uint64_t input_num) {
/* result might be undefined when input_num is zero */
really_inline int leading_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
unsigned long leading_zero = 0;
// Search the mask data from most significant bit (MSB)
// to least significant bit (LSB) for a set bit (1).
@ -4016,10 +4075,10 @@ really_inline int leading_zeroes(uint64_t input_num) {
return 64;
#else
return __builtin_clzll(input_num);
#endif// _MSC_VER
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
}
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
really_inline unsigned __int64 count_ones(uint64_t input_num) {
// note: we do not support legacy 32-bit Windows
return __popcnt64(input_num);// Visual Studio wants two underscores
@ -4032,7 +4091,7 @@ really_inline long long int count_ones(uint64_t input_num) {
really_inline bool add_overflow(uint64_t value1, uint64_t value2,
uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
return _addcarry_u64(0, value1, value2,
reinterpret_cast<unsigned __int64 *>(result));
#else
@ -4041,12 +4100,12 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2,
#endif
}
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
#pragma intrinsic(_umul128)
#endif
really_inline bool mul_overflow(uint64_t value1, uint64_t value2,
uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
uint64_t high;
*result = _umul128(value1, value2, &high);
return high;
@ -5789,7 +5848,7 @@ struct value128 {
uint64_t high;
};
#if defined(_MSC_VER) && !defined(_M_X64) // _umul128 for x86, arm, arm64
#if defined(SIMDJSON_REGULAR_VISUAL_STUDIO) && !defined(_M_X64) // _umul128 for x86, arm, arm64
#if defined(_M_ARM)
static inline uint64_t __emulu(uint32_t x, uint32_t y) {
return x * (uint64_t)y;
@ -5808,7 +5867,7 @@ static inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
really_inline value128 full_multiplication(uint64_t value1, uint64_t value2) {
value128 answer;
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
answer.low = _umul128(value1, value2, &answer.high);
#else
__uint128_t r = ((__uint128_t)value1) * value2;

View File

@ -1,4 +1,4 @@
/* auto-generated on Thu Apr 23 15:36:58 PDT 2020. Do not edit! */
/* auto-generated on Mon 27 Apr 2020 21:20:37 EDT. Do not edit! */
/* begin file simdjson.h */
#ifndef SIMDJSON_H
#define SIMDJSON_H
@ -46,40 +46,6 @@
#endif // SIMDJSON_COMPILER_CHECK_H
/* end file */
// Public API
/* begin file simdjson/simdjson_version.h */
// /include/simdjson/simdjson_version.h automatically generated by release.py,
// do not change by hand
#ifndef SIMDJSON_SIMDJSON_VERSION_H
#define SIMDJSON_SIMDJSON_VERSION_H
/** The version of simdjson being used (major.minor.revision) */
#define SIMDJSON_VERSION 0.3.1
namespace simdjson {
enum {
/**
* The major version (MAJOR.minor.revision) of simdjson being used.
*/
SIMDJSON_VERSION_MAJOR = 0,
/**
* The minor version (major.MINOR.revision) of simdjson being used.
*/
SIMDJSON_VERSION_MINOR = 3,
/**
* The revision (major.minor.REVISION) of simdjson being used.
*/
SIMDJSON_VERSION_REVISION = 1
};
} // namespace simdjson
#endif // SIMDJSON_SIMDJSON_VERSION_H
/* end file */
/* begin file simdjson/error.h */
#ifndef SIMDJSON_ERROR_H
#define SIMDJSON_ERROR_H
/* begin file simdjson/common_defs.h */
#ifndef SIMDJSON_COMMON_DEFS_H
#define SIMDJSON_COMMON_DEFS_H
@ -92,30 +58,57 @@ enum {
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#ifdef _MSC_VER
#define SIMDJSON_VISUAL_STUDIO 1
/**
* We want to differentiate carefully between
* clang under visual studio and regular visual
* studio.
*
* Under clang for Windows, we enable:
* * target pragmas so that part and only part of the
* code gets compiled for advanced instructions.
* * computed gotos.
*
*/
#ifdef __clang__
// clang under visual studio
#define SIMDJSON_CLANG_VISUAL_STUDIO 1
#else
// just regular visual studio (best guess)
#define SIMDJSON_REGULAR_VISUAL_STUDIO 1
#endif // __clang__
#endif // _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
// https://en.wikipedia.org/wiki/C_alternative_tokens
// This header should have no effect, except maybe
// under Visual Studio.
#include <iso646.h>
#endif
#if defined(__x86_64__) || defined(_M_AMD64)
#define IS_X86_64 1
#define SIMDJSON_IS_X86_64 1
#endif
#if defined(__aarch64__) || defined(_M_ARM64)
#define IS_ARM64 1
#define SIMDJSON_IS_ARM64 1
#endif
#if (!defined(IS_X86_64)) && (!defined(IS_ARM64))
#if _MSC_VER
#if (!defined(SIMDJSON_IS_X86_64)) && (!defined(SIMDJSON_IS_ARM64))
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
#pragma message("The simdjson library is designed\
for 64-bit processors and it seems that you are not\
compiling for a known 64-bit platform. All fast kernels\
will be disabled and performance may be poor. Please\
use a 64-bt target such as x64 or 64-bit ARM.")
for 64-bit processors and it seems that you are not \
compiling for a known 64-bit platform. All fast kernels \
will be disabled and performance may be poor. Please \
use a 64-bit target such as x64 or 64-bit ARM.")
#else
#error "The simdjson library is designed\
for 64-bit processors. It seems that you are not\
for 64-bit processors. It seems that you are not \
compiling for a known 64-bit platform."
#endif
#endif // (!defined(IS_X86_64)) && (!defined(IS_ARM64))
#endif // (!defined(SIMDJSON_IS_X86_64)) && (!defined(SIMDJSON_IS_ARM64))
// this is almost standard?
#undef STRINGIFY_IMPLEMENTATION_
@ -127,15 +120,15 @@ compiling for a known 64-bit platform."
#define SIMDJSON_IMPLEMENTATION_FALLBACK 1
#endif
#if IS_ARM64
#if SIMDJSON_IS_ARM64
#ifndef SIMDJSON_IMPLEMENTATION_ARM64
#define SIMDJSON_IMPLEMENTATION_ARM64 1
#endif
#define SIMDJSON_IMPLEMENTATION_HASWELL 0
#define SIMDJSON_IMPLEMENTATION_WESTMERE 0
#endif // IS_ARM64
#endif // SIMDJSON_IS_ARM64
#if IS_X86_64
#if SIMDJSON_IS_X86_64
#ifndef SIMDJSON_IMPLEMENTATION_HASWELL
#define SIMDJSON_IMPLEMENTATION_HASWELL 1
#endif
@ -143,10 +136,10 @@ compiling for a known 64-bit platform."
#define SIMDJSON_IMPLEMENTATION_WESTMERE 1
#endif
#define SIMDJSON_IMPLEMENTATION_ARM64 0
#endif // IS_X86_64
#endif // SIMDJSON_IS_X86_64
// we are going to use runtime dispatch
#ifdef IS_X86_64
#ifdef SIMDJSON_IS_X86_64
#ifdef __clang__
// clang does not have GCC push pop
// warning: clang attribute push can't be used within a namespace in clang up
@ -203,11 +196,10 @@ compiling for a known 64-bit platform."
#define NO_SANITIZE_UNDEFINED
#endif
#ifdef _MSC_VER
#include <intrin.h> // visual studio
#endif
#ifdef _MSC_VER
#ifdef SIMDJSON_VISUAL_STUDIO
// This is one case where we do not distinguish between
// regular visual studio and clang under visual studio.
// clang under Windows has _stricmp (like visual studio) but not strcasecmp (as clang normally has)
#define simdjson_strcasecmp _stricmp
#else
#define simdjson_strcasecmp strcasecmp
@ -217,7 +209,7 @@ namespace simdjson {
/** @private portable version of posix_memalign */
static inline void *aligned_malloc(size_t alignment, size_t size) {
void *p;
#ifdef _MSC_VER
#ifdef SIMDJSON_VISUAL_STUDIO
p = _aligned_malloc(size, alignment);
#elif defined(__MINGW32__) || defined(__MINGW64__)
p = __mingw_aligned_malloc(size, alignment);
@ -241,7 +233,7 @@ static inline void aligned_free(void *mem_block) {
if (mem_block == nullptr) {
return;
}
#ifdef _MSC_VER
#ifdef SIMDJSON_VISUAL_STUDIO
_aligned_free(mem_block);
#elif defined(__MINGW32__) || defined(__MINGW64__)
__mingw_aligned_free(mem_block);
@ -301,9 +293,12 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
#define DEBUG_BLOCK(name, block)
#endif
#if !defined(_MSC_VER) && !defined(SIMDJSON_NO_COMPUTED_GOTO)
#if !defined(SIMDJSON_REGULAR_VISUAL_STUDIO) && !defined(SIMDJSON_NO_COMPUTED_GOTO)
// We assume here that *only* regular visual studio
// does not support computed gotos.
// Implemented using Labels as Values which works in GCC and CLANG (and maybe
// also in Intel's compiler), but won't work in MSVC.
// Compute gotos are good for performance, enable them if you can.
#define SIMDJSON_USE_COMPUTED_GOTO
#endif
@ -313,7 +308,7 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
#define ISALIGNED_N(ptr, n) (((uintptr_t)(ptr) & ((n)-1)) == 0)
#ifdef _MSC_VER
#if defined(SIMDJSON_REGULAR_VISUAL_STUDIO)
#define really_inline __forceinline
#define never_inline __declspec(noinline)
@ -334,13 +329,7 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
#define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_VS_WARNING(4996)
#define SIMDJSON_POP_DISABLE_WARNINGS __pragma(warning( pop ))
#if SIMDJSON_USING_LIBRARY
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport)
#else
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllexport)
#endif
#else // MSC_VER
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
#define really_inline inline __attribute__((always_inline, unused))
#define never_inline inline __attribute__((noinline, unused))
@ -373,11 +362,24 @@ constexpr size_t DEFAULT_MAX_DEPTH = 1024;
#define SIMDJSON_DISABLE_DEPRECATED_WARNING SIMDJSON_DISABLE_GCC_WARNING(-Wdeprecated-declarations)
#define SIMDJSON_POP_DISABLE_WARNINGS _Pragma("GCC diagnostic pop")
#define SIMDJSON_DLLIMPORTEXPORT
#endif // MSC_VER
#if defined(SIMDJSON_VISUAL_STUDIO)
/**
* It does not matter here whether you are using
* the regular visual studio or clang under visual
* studio.
*/
#if SIMDJSON_USING_LIBRARY
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllimport)
#else
#define SIMDJSON_DLLIMPORTEXPORT __declspec(dllexport)
#endif
#else
#define SIMDJSON_DLLIMPORTEXPORT
#endif
// C++17 requires string_view.
#if SIMDJSON_CPLUSPLUS17
@ -1962,6 +1964,45 @@ namespace std {
#endif // SIMDJSON_COMMON_DEFS_H
/* end file */
SIMDJSON_PUSH_DISABLE_WARNINGS
#if defined(_MSC_VER) && defined(__clang__)
SIMDJSON_DISABLE_GCC_WARNING(-Wmicrosoft-include)
#endif
// Public API
/* begin file simdjson/simdjson_version.h */
// /include/simdjson/simdjson_version.h automatically generated by release.py,
// do not change by hand
#ifndef SIMDJSON_SIMDJSON_VERSION_H
#define SIMDJSON_SIMDJSON_VERSION_H
/** The version of simdjson being used (major.minor.revision) */
#define SIMDJSON_VERSION 0.3.1
namespace simdjson {
enum {
/**
* The major version (MAJOR.minor.revision) of simdjson being used.
*/
SIMDJSON_VERSION_MAJOR = 0,
/**
* The minor version (major.MINOR.revision) of simdjson being used.
*/
SIMDJSON_VERSION_MINOR = 3,
/**
* The revision (major.minor.REVISION) of simdjson being used.
*/
SIMDJSON_VERSION_REVISION = 1
};
} // namespace simdjson
#endif // SIMDJSON_SIMDJSON_VERSION_H
/* end file */
/* begin file simdjson/error.h */
#ifndef SIMDJSON_ERROR_H
#define SIMDJSON_ERROR_H
#include <string>
#include <utility>
@ -2298,7 +2339,7 @@ private:
padded_string &operator=(const padded_string &o) = delete;
padded_string(const padded_string &o) = delete;
size_t viable_size;
size_t viable_size{0};
char *data_ptr{nullptr};
}; // padded_string
@ -4316,7 +4357,7 @@ inline std::ostream& operator<<(std::ostream& out, const escape_json_string &une
namespace simdjson {
class [[deprecated("Use the new DOM navigation API instead (see doc/usage.md)")]] dom::parser::Iterator {
class [[deprecated("Use the new DOM navigation API instead (see doc/basics.md)")]] dom::parser::Iterator {
public:
inline Iterator(const dom::parser &parser) noexcept(false);
inline Iterator(const Iterator &o) noexcept;
@ -6206,7 +6247,7 @@ inline char *allocate_padded_buffer(size_t length) noexcept {
} // namespace internal
inline padded_string::padded_string() noexcept : viable_size(0), data_ptr(nullptr) {}
inline padded_string::padded_string() noexcept {}
inline padded_string::padded_string(size_t length) noexcept
: viable_size(length), data_ptr(internal::allocate_padded_buffer(length)) {
if (data_ptr != nullptr)
@ -6561,8 +6602,7 @@ dom::parser::Iterator::Iterator(
location(o.location),
tape_length(o.tape_length),
current_type(o.current_type),
current_val(o.current_val),
depth_index()
current_val(o.current_val)
{
depth_index = new scopeindex_t[max_depth+1];
memcpy(depth_index, o.depth_index, (depth + 1) * sizeof(depth_index[0]));
@ -6799,5 +6839,7 @@ SIMDJSON_POP_DISABLE_WARNINGS
#endif // SIMDJSON_INLINE_PARSEDJSON_ITERATOR_H
/* end file */
SIMDJSON_POP_DISABLE_WARNINGS
#endif // SIMDJSON_H
/* end file */

View File

@ -12,15 +12,15 @@ namespace arm64 {
// Sadly, sanitizers are not smart enough to figure it out.
NO_SANITIZE_UNDEFINED
really_inline int trailing_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
unsigned long ret;
// Search the mask data from least significant bit (LSB)
// to the most significant bit (MSB) for a set bit (1).
_BitScanForward64(&ret, input_num);
return (int)ret;
#else // _MSC_VER
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
return __builtin_ctzll(input_num);
#endif // _MSC_VER
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
}
/* result might be undefined when input_num is zero */
@ -30,7 +30,7 @@ really_inline uint64_t clear_lowest_bit(uint64_t input_num) {
/* result might be undefined when input_num is zero */
really_inline int leading_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
unsigned long leading_zero = 0;
// Search the mask data from most significant bit (MSB)
// to least significant bit (LSB) for a set bit (1).
@ -40,7 +40,7 @@ really_inline int leading_zeroes(uint64_t input_num) {
return 64;
#else
return __builtin_clzll(input_num);
#endif// _MSC_VER
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
}
/* result might be undefined when input_num is zero */
@ -49,7 +49,7 @@ really_inline int count_ones(uint64_t input_num) {
}
really_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
*result = value1 + value2;
return *result < value1;
#else
@ -59,7 +59,7 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *resu
}
really_inline bool mul_overflow(uint64_t value1, uint64_t value2, uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
*result = value1 * value2;
return !!__umulh(value1, value2);
#else

View File

@ -14,16 +14,16 @@ namespace haswell {
// Sadly, sanitizers are not smart enough to figure it out.
NO_SANITIZE_UNDEFINED
really_inline int trailing_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
return (int)_tzcnt_u64(input_num);
#else // _MSC_VER
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
////////
// You might expect the next line to be equivalent to
// return (int)_tzcnt_u64(input_num);
// but the generated code differs and might be less efficient?
////////
return __builtin_ctzll(input_num);
#endif // _MSC_VER
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
}
/* result might be undefined when input_num is zero */
@ -36,7 +36,7 @@ really_inline int leading_zeroes(uint64_t input_num) {
return int(_lzcnt_u64(input_num));
}
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
really_inline unsigned __int64 count_ones(uint64_t input_num) {
// note: we do not support legacy 32-bit Windows
return __popcnt64(input_num);// Visual Studio wants two underscores
@ -49,7 +49,7 @@ really_inline long long int count_ones(uint64_t input_num) {
really_inline bool add_overflow(uint64_t value1, uint64_t value2,
uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
return _addcarry_u64(0, value1, value2,
reinterpret_cast<unsigned __int64 *>(result));
#else
@ -58,12 +58,12 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2,
#endif
}
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
#pragma intrinsic(_umul128)
#endif
really_inline bool mul_overflow(uint64_t value1, uint64_t value2,
uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
uint64_t high;
*result = _umul128(value1, value2, &high);
return high;

View File

@ -3,17 +3,52 @@
#include "simdjson.h"
#ifdef _MSC_VER
// visual studio (or clang-cl)
#include <intrin.h>
#ifdef __clang__
#include <bmiintrin.h>
#include <lzcntintrin.h>
#include <immintrin.h>
#include <wmmintrin.h>
#endif
#ifdef SIMDJSON_VISUAL_STUDIO
// under clang within visual studio, this will include <x86intrin.h>
#include <intrin.h> // visual studio or clang
#else
#include <x86intrin.h> // elsewhere
#endif // _MSC_VER
#endif // SIMDJSON_VISUAL_STUDIO
#ifdef SIMDJSON_CLANG_VISUAL_STUDIO
/**
* You are not supposed, normally, to include these
* headers directly. Instead you should either include intrin.h
* or x86intrin.h. However, when compiling with clang
* under Windows (i.e., when _MSC_VER is set), these headers
* only get included *if* the corresponding features are detected
* from macros:
* e.g., if __AVX2__ is set... in turn, we normally set these
* macros by compiling against the corresponding architecture
* (e.g., arch:AVX2, -mavx2, etc.) which compiles the whole
* software with these advanced instructions. In simdjson, we
* want to compile the whole program for a generic target,
* and only target our specific kernels. As a workaround,
* we directly include the needed headers. These headers would
* normally guard against such usage, but we carefully included
* <x86intrin.h> (or <intrin.h>) before, so the headers
* are fooled.
*/
#include <bmiintrin.h> // for _blsr_u64
#include <lzcntintrin.h> // for __lzcnt64
#include <immintrin.h> // for most things (AVX2, AVX512, _popcnt64)
#include <smmintrin.h>
#include <tmmintrin.h>
#include <avxintrin.h>
#include <avx2intrin.h>
#include <wmmintrin.h> // for _mm_clmulepi64_si128
// unfortunately, we may not get _blsr_u64, but, thankfully, clang
// has it as a macro.
#ifndef _blsr_u64
// we roll our own
TARGET_HASWELL
static really_inline uint64_t simdjson_blsr_u64(uint64_t n) {
return (n - 1) & n;
}
UNTARGET_REGION
#define _blsr_u64(a) (simdjson_blsr_u64((a)))
#endif // _blsr_u64
#endif
#endif // SIMDJSON_HASWELL_INTRINSICS_H

View File

@ -324,7 +324,7 @@ struct value128 {
uint64_t high;
};
#if defined(_MSC_VER) && !defined(_M_X64) // _umul128 for x86, arm, arm64
#if defined(SIMDJSON_REGULAR_VISUAL_STUDIO) && !defined(_M_X64) // _umul128 for x86, arm, arm64
#if defined(_M_ARM)
static inline uint64_t __emulu(uint32_t x, uint32_t y) {
return x * (uint64_t)y;
@ -343,7 +343,7 @@ static inline uint64_t _umul128(uint64_t ab, uint64_t cd, uint64_t *hi) {
really_inline value128 full_multiplication(uint64_t value1, uint64_t value2) {
value128 answer;
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
answer.low = _umul128(value1, value2, &answer.high);
#else
__uint128_t r = ((__uint128_t)value1) * value2;

View File

@ -1,13 +1,9 @@
#include "simdjson.h"
#if defined(_MSC_VER) && defined(__clang__)
#if defined(SIMDJSON_CLANG_VISUAL_STUDIO)
SIMDJSON_DISABLE_GCC_WARNING(-Wmicrosoft-include)
#endif
/* used for http://dmalloc.com/ Dmalloc - Debug Malloc Library */
#ifdef DMALLOC
#include "dmalloc.h"
#endif
#include "error.cpp"
#include "implementation.cpp"

View File

@ -13,15 +13,15 @@ namespace westmere {
// Sadly, sanitizers are not smart enough to figure it out.
NO_SANITIZE_UNDEFINED
really_inline int trailing_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
unsigned long ret;
// Search the mask data from least significant bit (LSB)
// to the most significant bit (MSB) for a set bit (1).
_BitScanForward64(&ret, input_num);
return (int)ret;
#else // _MSC_VER
#else // SIMDJSON_REGULAR_VISUAL_STUDIO
return __builtin_ctzll(input_num);
#endif // _MSC_VER
#endif // SIMDJSON_REGULAR_VISUAL_STUDIO
}
/* result might be undefined when input_num is zero */
@ -31,7 +31,7 @@ really_inline uint64_t clear_lowest_bit(uint64_t input_num) {
/* result might be undefined when input_num is zero */
really_inline int leading_zeroes(uint64_t input_num) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
unsigned long leading_zero = 0;
// Search the mask data from most significant bit (MSB)
// to least significant bit (LSB) for a set bit (1).
@ -41,10 +41,10 @@ really_inline int leading_zeroes(uint64_t input_num) {
return 64;
#else
return __builtin_clzll(input_num);
#endif// _MSC_VER
#endif// SIMDJSON_REGULAR_VISUAL_STUDIO
}
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
really_inline unsigned __int64 count_ones(uint64_t input_num) {
// note: we do not support legacy 32-bit Windows
return __popcnt64(input_num);// Visual Studio wants two underscores
@ -57,7 +57,7 @@ really_inline long long int count_ones(uint64_t input_num) {
really_inline bool add_overflow(uint64_t value1, uint64_t value2,
uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
return _addcarry_u64(0, value1, value2,
reinterpret_cast<unsigned __int64 *>(result));
#else
@ -66,12 +66,12 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2,
#endif
}
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
#pragma intrinsic(_umul128)
#endif
really_inline bool mul_overflow(uint64_t value1, uint64_t value2,
uint64_t *result) {
#ifdef _MSC_VER
#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO
uint64_t high;
*result = _umul128(value1, value2, &high);
return high;

View File

@ -1,10 +1,27 @@
#ifndef SIMDJSON_WESTMERE_INTRINSICS_H
#define SIMDJSON_WESTMERE_INTRINSICS_H
#ifdef _MSC_VER
#include <intrin.h> // visual studio
#ifdef SIMDJSON_VISUAL_STUDIO
// under clang within visual studio, this will include <x86intrin.h>
#include <intrin.h> // visual studio or clang
#else
#include <x86intrin.h> // elsewhere
#endif // _MSC_VER
#endif // SIMDJSON_VISUAL_STUDIO
#ifdef SIMDJSON_CLANG_VISUAL_STUDIO
/**
* You are not supposed, normally, to include these
* headers directly. Instead you should either include intrin.h
* or x86intrin.h. However, when compiling with clang
* under Windows (i.e., when _MSC_VER is set), these headers
* only get included *if* the corresponding features are detected
* from macros:
*/
#include <smmintrin.h> // for _mm_alignr_epi8
#include <wmmintrin.h> // for _mm_clmulepi64_si128
#endif
#endif // SIMDJSON_WESTMERE_INTRINSICS_H

View File

@ -110,7 +110,7 @@ char *optarg; /* argument associated with option */
extern char __declspec(dllimport) *__progname;
#endif
#ifdef __CYGWIN__
#if defined(__CYGWIN__) || defined(__clang__) // D. Lemire (April 2020): adding __clang__
static char EMSG[] = "";
#else
#define EMSG ""