[gtk+] gtk/gtkcssenumvalue.c: Deal with __builtin_popcount on MSVC



commit 20fc576275fc4df0fb33fd0dc24c799bef512b79
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Tue Oct 24 16:16:08 2017 +0800

    gtk/gtkcssenumvalue.c: Deal with __builtin_popcount on MSVC
    
    __builtin_popcount is a GCCism that is used to count the number of bits
    involved, which means any non GCC/CLang compilers won't like the code,
    meaning that on MSVC builds we must implement it ourselves.
    
    We first use __cpuid() to check whether the CPU supports the popcount
    instruction, if it does, we use the __popcnt intrinsic, otherwise
    (untested, since I don't have a system that does not have the
    instruction), we use the suggested hacks at
    http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773299

 gtk/gtkcssenumvalue.c |   37 +++++++++++++++++++++++++++++++++++++
 1 files changed, 37 insertions(+), 0 deletions(-)
---
diff --git a/gtk/gtkcssenumvalue.c b/gtk/gtkcssenumvalue.c
index f5a0aa0..cac3600 100644
--- a/gtk/gtkcssenumvalue.c
+++ b/gtk/gtkcssenumvalue.c
@@ -24,6 +24,10 @@
 #include "gtkstyleproviderprivate.h"
 #include "gtksettingsprivate.h"
 
+#ifdef _MSC_VER
+# include <intrin.h>
+#endif
+
 /* repeated API */
 
 struct _GtkCssValue {
@@ -1429,6 +1433,39 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN = {
   gtk_css_font_variant_east_asian_value_print
 };
 
+#ifdef _MSC_VER
+/* __builtin_popcount is a GCC-only function
+   so we need to define it for ourselves somehow */
+
+static inline guint
+__msvc_compat_popcnt (guint32 value)
+{
+  static gssize popcnt_checked = 0;
+  static gboolean have_popcnt = FALSE;
+
+# if defined (_M_AMD64) || defined (_M_X64) || (_M_IX86)
+  if (g_once_init_enter (&popcnt_checked))
+    {
+      int cpuinfo[4] = {-1};
+
+         __cpuid (cpuinfo, 1);
+      have_popcnt =  (cpuinfo[2] & 0x00800000) != 0;
+      g_once_init_leave (&popcnt_checked, 1);
+    }
+# endif
+
+  if (have_popcnt)
+    return __popcnt (value);
+  else
+    /* http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel */
+    return (((value & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) +
+           ((((value & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) +
+           (((value >> 24) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f);
+}
+
+# define __builtin_popcount(v) __msvc_compat_popcnt(v)
+#endif
+
 static gboolean
 east_asian_value_is_valid (GtkCssFontVariantEastAsian east_asian)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]