Skip to content

Commit

Permalink
Add MSVC ARM support (DRQS 175608460) (#4788)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rostislav Khlebnikov authored and GitHub Enterprise committed Jun 20, 2024
1 parent ebe6ef3 commit f67a403
Show file tree
Hide file tree
Showing 14 changed files with 761 additions and 16 deletions.
25 changes: 20 additions & 5 deletions groups/bdl/bdlb/bdlb_bitutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ BSLS_IDENT("$Id: $")
#include <intrin.h>
# define BDLB_BITUTIL_USE_MSVC_INTRINSICS 1
// Use the intrinsics that map directly to CPU instructions on MSVC

# if defined(BSLS_PLATFORM_CPU_ARM)
# define BDLB_BITUTIL_USE_MSVC_COUNT_ONE_BITS 1
// Use _CountOneBits instead of __popcnt intrinsics on MSVC
# endif

#endif

namespace BloombergLP {
Expand Down Expand Up @@ -320,7 +326,11 @@ int BitUtil::numBitsSet(unsigned int value)
#elif defined(BDLB_BITUTIL_USE_GNU_INTRINSICS)
return __builtin_popcount(value);
#elif defined(BDLB_BITUTIL_USE_MSVC_INTRINSICS)
# if !defined(BDLB_BITUTIL_USE_MSVC_COUNT_ONE_BITS)
return __popcnt(value);
# else
return _CountOneBits(value);
# endif
#else
return privateNumBitsSet(value);
#endif
Expand All @@ -334,12 +344,17 @@ int BitUtil::numBitsSet(unsigned long long value)
#elif defined(BDLB_BITUTIL_USE_GNU_INTRINSICS)
return __builtin_popcountll(value);
#elif defined(BDLB_BITUTIL_USE_MSVC_INTRINSICS)
#if defined(BSLS_PLATFORM_CPU_64_BIT)
return static_cast<int>(__popcnt64(value));
#if !defined(BDLB_BITUTIL_USE_MSVC_COUNT_ONE_BITS)
#if defined(BSLS_PLATFORM_CPU_64_BIT)
return static_cast<int>(__popcnt64(value));
#else
// '__popcnt64' available only in 64bit target
return __popcnt(static_cast<unsigned int>(value)) +
__popcnt(static_cast<unsigned int>(value >>
k_BITS_PER_INT32));
#endif
#else
// '__popcnt64' available only in 64bit target
return __popcnt(static_cast<unsigned int>(value)) +
__popcnt(static_cast<unsigned int>(value >> k_BITS_PER_INT32));
return _CountOneBits64(value);
#endif
#else
return privateNumBitsSet(value);
Expand Down
2 changes: 1 addition & 1 deletion groups/bdl/bdlpcre/bdlpcre_regex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ bool RegEx::isJitAvailable()
unsigned int result = 0;
(void) result;

#if !(defined(BSLS_PLATFORM_OS_DARWIN) && defined(BSLS_PLATFORM_CPU_ARM))
#if !defined(BSLS_PLATFORM_CPU_ARM)
// Currently pcre2_config incorrectly reports JIT support is available for
// Apple M1 hardware, but it currently does not work.

Expand Down
2 changes: 1 addition & 1 deletion groups/bsl/bslmf/bslmf_invokeresult.00.t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ void aSsErT(bool condition, const char *message, int line)

#if defined(BSLS_PLATFORM_CMP_MSVC) \
&& BSLS_PLATFORM_CMP_VERSION >= 1930 \
&& BSLS_PLATFORM_CMP_VERSION <= 1939
&& BSLS_PLATFORM_CMP_VERSION <= 1940
#define MSVC_2022 1
#else
#define MSVC_2022 0
Expand Down
6 changes: 6 additions & 0 deletions groups/bsl/bsls/bsls_atomicoperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,12 @@ BSLS_IDENT("$Id: $")
#elif defined(BSLS_PLATFORM_CPU_ARM)
# if defined(BSLS_PLATFORM_CMP_GNU) || defined(BSLS_PLATFORM_CMP_CLANG)
# include <bsls_atomicoperations_arm_all_gcc.h>
# elif defined(BSLS_PLATFORM_CMP_MSVC)
# if defined(BSLS_PLATFORM_CPU_64_BIT)
# include <bsls_atomicoperations_arm64_win_msvc.h>
# else
# include <bsls_atomicoperations_arm32_win_msvc.h>
# endif
# else
# define BSLS_ATOMICOPERATIONS_ERROR
# endif
Expand Down
30 changes: 30 additions & 0 deletions groups/bsl/bsls/bsls_atomicoperations_arm32_win_msvc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// bsls_atomicoperations_arm32_win_msvc.cpp -*-C++-*-

#include <bsls_atomicoperations_arm32_win_msvc.h>

#include <bsls_ident.h>
BSLS_IDENT("$Id$ $CSID$")

#if defined(BSLS_PLATFORM_CPU_ARM) && defined(BSLS_PLATFORM_CPU_32_BIT) && \
defined(BSLS_PLATFORM_CMP_MSVC)

namespace BloombergLP {
} // close namespace BloombergLP

#endif

// ----------------------------------------------------------------------------
// Copyright 2024 Bloomberg Finance L.P.
//
// 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.
// ----------------------------- END-OF-FILE ----------------------------------
271 changes: 271 additions & 0 deletions groups/bsl/bsls/bsls_atomicoperations_arm32_win_msvc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
// bsls_atomicoperations_arm32_win_msvc.h -*-C++-*-
#ifndef INCLUDED_BSLS_ATOMICOPERATIONS_ARM32_WIN_MSVC
#define INCLUDED_BSLS_ATOMICOPERATIONS_ARM32_WIN_MSVC

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide implementations of atomic operations for arm32/MSVC/Win.
//
//@CLASSES:
// bsls::AtomicOperations_ARM32_WIN_MSVC: atomics for arm32/MSVC/Windows
//
//@DESCRIPTION: This component provides classes necessary to implement atomics
// on the Windows platform with MSVC compiler for ARM CPUs. The classes are
// for private use only. See 'bsls_atomicoperations' and 'bsls_atomic' for
// the public interface to atomics.

#include <bsls_atomicoperations_default.h>
#include <bsls_platform.h>
#include <bsls_types.h>

#if defined(BSLS_PLATFORM_CPU_ARM) && defined(BSLS_PLATFORM_CPU_32_BIT) && \
defined(BSLS_PLATFORM_CMP_MSVC)
#include <intrin.h>

namespace BloombergLP {

namespace bsls {

struct AtomicOperations_ARM32_WIN_MSVC;
typedef AtomicOperations_ARM32_WIN_MSVC AtomicOperations_Imp;

// =========================================================
// struct Atomic_TypeTraits<AtomicOperations_ARM32_WIN_MSVC>
// =========================================================

template<>
struct Atomic_TypeTraits<AtomicOperations_ARM32_WIN_MSVC>
{
struct Int
{
__declspec(align(4))
volatile int d_value;
};

struct Int64
{
__declspec(align(8))
volatile Types::Int64 d_value;
};

struct Uint
{
__declspec(align(4))
volatile unsigned int d_value;
};

struct Uint64
{
__declspec(align(8))
volatile Types::Uint64 d_value;
};

struct Pointer
{
__declspec(align(4))
void * volatile d_value;
};
};

// ======================================
// struct AtomicOperations_ARM32_WIN_MSVC
// ======================================

struct AtomicOperations_ARM32_WIN_MSVC
: AtomicOperations_Default32<AtomicOperations_ARM32_WIN_MSVC>
{
typedef Atomic_TypeTraits<AtomicOperations_ARM32_WIN_MSVC> AtomicTypes;

// *** atomic functions for int ***

static int getInt(const AtomicTypes::Int *atomicInt);

static int getIntAcquire(const AtomicTypes::Int *atomicInt);

static void setInt(AtomicTypes::Int *atomicInt, int value);

static void setIntRelease(AtomicTypes::Int *atomicInt, int value);

static int swapInt(AtomicTypes::Int *atomicInt, int swapValue);

static int testAndSwapInt(AtomicTypes::Int *atomicInt,
int compareValue,
int swapValue);

static int addIntNv(AtomicTypes::Int *atomicInt, int value);

// *** atomic functions for Int64 ***

static Types::Int64 getInt64(const AtomicTypes::Int64 *atomicInt);

static void setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value);

static Types::Int64 swapInt64(AtomicTypes::Int64 *atomicInt,
Types::Int64 swapValue);

static Types::Int64 testAndSwapInt64(AtomicTypes::Int64 *atomicInt,
Types::Int64 compareValue,
Types::Int64 swapValue);

static Types::Int64 addInt64Nv(AtomicTypes::Int64 *atomicInt,
Types::Int64 value);
};

// ===========================================================================
// INLINE FUNCTION DEFINITIONS
// ===========================================================================

// --------------------------------------
// struct AtomicOperations_ARM32_WIN_MSVC
// --------------------------------------

// Memory barrier for atomic operations with sequential consistency.
#define BSLS_ATOMIC_FENCE() \
__dmb(_ARM_BARRIER_ISH)

inline
int AtomicOperations_ARM32_WIN_MSVC::
getInt(const AtomicTypes::Int *atomicInt)
{
int result = __iso_volatile_load32(&atomicInt->d_value);
BSLS_ATOMIC_FENCE();
return result;
}

inline
int AtomicOperations_ARM32_WIN_MSVC::
getIntAcquire(const AtomicTypes::Int *atomicInt)
{
int result = __iso_volatile_load32(&atomicInt->d_value);
BSLS_ATOMIC_FENCE();
return result;
}

inline
void AtomicOperations_ARM32_WIN_MSVC::
setInt(AtomicTypes::Int *atomicInt, int value)
{
BSLS_ATOMIC_FENCE();
__iso_volatile_store32(&atomicInt->d_value, value);
BSLS_ATOMIC_FENCE();
}

inline
void AtomicOperations_ARM32_WIN_MSVC::
setIntRelease(AtomicTypes::Int *atomicInt, int value)
{
BSLS_ATOMIC_FENCE();
__iso_volatile_store32(&atomicInt->d_value, value);
}

inline
int AtomicOperations_ARM32_WIN_MSVC::
swapInt(AtomicTypes::Int *atomicInt, int swapValue)
{
return _InterlockedExchange(
reinterpret_cast<long volatile *>(&atomicInt->d_value),
swapValue);
}

inline
int AtomicOperations_ARM32_WIN_MSVC::
testAndSwapInt(AtomicTypes::Int *atomicInt,
int compareValue,
int swapValue)
{
return _InterlockedCompareExchange(
reinterpret_cast<long volatile *>(&atomicInt->d_value),
swapValue,
compareValue);
}

inline
int AtomicOperations_ARM32_WIN_MSVC::
addIntNv(AtomicTypes::Int *atomicInt, int value)
{
return static_cast<int>(
static_cast<unsigned int>(_InterlockedExchangeAdd(
reinterpret_cast<long volatile *>(&atomicInt->d_value),
value)) +
value);
}
// *** atomic functions for Int64 ***

inline
Types::Int64 AtomicOperations_ARM32_WIN_MSVC::
getInt64(const AtomicTypes::Int64 *atomicInt)
{
Types::Int64 result = __iso_volatile_load64(&atomicInt->d_value);
BSLS_ATOMIC_FENCE();
return result;
}

inline
void AtomicOperations_ARM32_WIN_MSVC::
setInt64(AtomicTypes::Int64 *atomicInt, Types::Int64 value)
{
BSLS_ATOMIC_FENCE();
__iso_volatile_store64(&atomicInt->d_value, value);
BSLS_ATOMIC_FENCE();
}

inline
Types::Int64 AtomicOperations_ARM32_WIN_MSVC::
swapInt64(AtomicTypes::Int64 *atomicInt,
Types::Int64 swapValue)
{
return _InterlockedExchange64(
&atomicInt->d_value,
swapValue);
}

inline
Types::Int64 AtomicOperations_ARM32_WIN_MSVC::
testAndSwapInt64(AtomicTypes::Int64 *atomicInt,
Types::Int64 compareValue,
Types::Int64 swapValue)
{
return _InterlockedCompareExchange64(
&atomicInt->d_value,
swapValue,
compareValue);
}

inline
Types::Int64 AtomicOperations_ARM32_WIN_MSVC::
addInt64Nv(AtomicTypes::Int64 *atomicInt,
Types::Int64 value)
{
return static_cast<Types::Int64>(
static_cast<Types::Uint64>(
_InterlockedExchangeAdd64(&atomicInt->d_value, value)) +
value);

}

#undef BSLS_ATOMIC_FENCE

} // close package namespace

} // close enterprise namespace

#endif // arm32 && MSVC

#endif

// ----------------------------------------------------------------------------
// Copyright 2024 Bloomberg Finance L.P.
//
// 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.
// ----------------------------- END-OF-FILE ----------------------------------
Loading

0 comments on commit f67a403

Please sign in to comment.