Add Compiler Condition to use inline assembly optimizations with ARM64 for Compatibility with MSVC (#17671)

https://github.com/protocolbuffers/protobuf/issues/17665

**Problem**
`google\protobuf\parse_context.h(721,10): error C2059: syntax error: ':'`
`google\protobuf\parse_context.h(898,14): error C3861: 'Ubfx7': identifier not found`

The latest protobuf versions fail to compile with MSVC on Windows ARM64 architecture.

> Inline assembly is only available for x86 targets. For similar functionality in x64 or ARM64 code, use [compiler intrinsics](https://learn.microsoft.com/en-us/cpp/intrinsics/compiler-intrinsics?view=msvc-170).

https://learn.microsoft.com/en-us/cpp/assembler/inline/writing-functions-with-inline-assembly?view=msvc-170

**Solution**
As inline assembly for win ARM64 with MSVC as a compiler is not supported (even ARM specific assembly functions), a term has been added to the conditions in parse_context.h to prevent the assembly optimizations for arm64 from executing if the compiler is MSVC.

Tested by compiling protobuf with MSVC on Windows ARM64 and AMD64 architecture. Compilation was a success.

Closes #17671

COPYBARA_INTEGRATE_REVIEW=https://github.com/protocolbuffers/protobuf/pull/17671 from dsmith111:smithdavi/msvc-compatibility-patch 765f8c8e7c
PiperOrigin-RevId: 663262760
pull/17822/head
David Smith 6 months ago committed by Copybara-Service
parent 5a224554eb
commit c5f623184d
  1. 4
      src/google/protobuf/parse_context.h

@ -635,7 +635,7 @@ inline const char* VarintParseSlow(const char* p, uint32_t res, uint64_t* out) {
return tmp.first;
}
#ifdef __aarch64__
#if defined(__aarch64__) && !defined(_MSC_VER)
// Generally, speaking, the ARM-optimized Varint decode algorithm is to extract
// and concatenate all potentially valid data bits, compute the actual length
// of the Varint, and mask off the data bits which are not actually part of the
@ -866,7 +866,7 @@ static const char* VarintParseSlowArm(const char* p, uint64_t* out,
// The caller must ensure that p points to at least 10 valid bytes.
template <typename T>
PROTOBUF_NODISCARD const char* VarintParse(const char* p, T* out) {
#if defined(__aarch64__) && defined(ABSL_IS_LITTLE_ENDIAN)
#if defined(__aarch64__) && defined(ABSL_IS_LITTLE_ENDIAN) && !defined(_MSC_VER)
// This optimization is not supported in big endian mode
uint64_t first8;
std::memcpy(&first8, p, sizeof(first8));

Loading…
Cancel
Save