zlib: fix ARMv8 CRC32 compilation in GCC

GCC compilation in ARM architectures with CRC32 extension was
broken, as the extension was guarded for clang.

For GCC we are enforcing armv8-a+crc architecture at module
level, so the builtin extensions are available. Then we
just include arm_acle.h to declare the required builtins.

ThinLTO requires all modules to use same target, so this
change makes GCC fail with ThinLTO (that was not supported
anyway). Added a GN assert to explicitely fail in this case.

Adapted from Vladislav Mukulov <vladislav.mukulov@lge.com>
original patch.

Bug: 819294
Change-Id: Ifa5cf64318f88220052c44126db90bef999b7113
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1642730
Reviewed-by: Adenilson Cavalcanti <cavalcantii@chromium.org>
Commit-Queue: José Dapena Paz <jose.dapena@lge.com>
Cr-Original-Commit-Position: refs/heads/master@{#667541}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: 68e95088b6f73f489aa1e1023b7864794627cae1
diff --git a/BUILD.gn b/BUILD.gn
index 1a9cd3b..3b8e5e9 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -89,7 +89,7 @@
   source_set("zlib_arm_crc32") {
     visibility = [ ":*" ]
 
-    if (is_clang && !is_ios) {
+    if (!is_ios) {
       include_dirs = [ "." ]
 
       if (is_android) {
@@ -101,6 +101,10 @@
         } else {
           assert(false, "CPU detection requires the Android NDK")
         }
+      } else if (!is_win && !is_clang) {
+        assert(!thin_lto_enable_optimizations,
+               "ThinLTO fails mixing different module-level targets")
+        cflags_c = [ "-march=armv8-a+crc" ]
       }
 
       sources = [
diff --git a/crc32_simd.c b/crc32_simd.c
index 03698ad..2fef610 100644
--- a/crc32_simd.c
+++ b/crc32_simd.c
@@ -161,6 +161,7 @@
  * TODO: implement a version using the PMULL instruction.
  */
 
+#if defined(__clang__)
 /* CRC32 intrinsics are #ifdef'ed out of arm_acle.h unless we build with an
  * armv8 target, which is incompatible with ThinLTO optimizations on Android.
  * (Namely, mixing and matching different module-level targets makes ThinLTO
@@ -183,8 +184,18 @@
 
 #if defined(__aarch64__)
 #define TARGET_ARMV8_WITH_CRC __attribute__((target("crc")))
-#else
+#else  // !defined(__aarch64__)
 #define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc")))
+#endif  // defined(__aarch64__)
+
+#elif defined(__GNUC__)
+/* For GCC, we are setting CRC extensions at module level, so ThinLTO is not
+ * allowed. We can just include arm_acle.h.
+ */
+#include <arm_acle.h>
+#define TARGET_ARMV8_WITH_CRC
+#else  // !defined(__GNUC__) && !defined(_aarch64__)
+#error ARM CRC32 SIMD extensions only supported for Clang and GCC
 #endif
 
 TARGET_ARMV8_WITH_CRC
@@ -248,5 +259,4 @@
     return ret;
 }
 
-
 #endif