From c5f623184dc91e5c5bc58adb91b93f24e4467282 Mon Sep 17 00:00:00 2001 From: David Smith <68763658+dsmith111@users.noreply.github.com> Date: Thu, 15 Aug 2024 04:43:26 -0700 Subject: [PATCH] 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 765f8c8e7c5984546b3da9e6251d919579319604 PiperOrigin-RevId: 663262760 --- src/google/protobuf/parse_context.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h index d40e71c1dc62..22ed8212dfa6 100644 --- a/src/google/protobuf/parse_context.h +++ b/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 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));