From 20fc576275fc4df0fb33fd0dc24c799bef512b79 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Tue, 24 Oct 2017 16:16:08 +0800 Subject: [PATCH] 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 file changed, 37 insertions(+) diff --git a/gtk/gtkcssenumvalue.c b/gtk/gtkcssenumvalue.c index f5a0aa0266..cac36006b5 100644 --- a/gtk/gtkcssenumvalue.c +++ b/gtk/gtkcssenumvalue.c @@ -24,6 +24,10 @@ #include "gtkstyleproviderprivate.h" #include "gtksettingsprivate.h" +#ifdef _MSC_VER +# include +#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) {