On 10/1/19 1:35 AM, Paul Eggert wrote:
Actually those arrays use int_fast16_t not int16_t, as C99/C11/C18 does not require support for int16_t. It could well be more efficient for them to use int_least16_t instead, for better caching

Attached is a proposed patch to implement this for Bison. This patch also fixes some portability problems for odd machines like the TI TMS320C55x where 'unsigned char', 'unsigned short', and 'unsigned' are all the same width (which C allows), and where picky -Wconversion compilers warn about assigning an unsigned char value to an int variable.

Comments welcome; I haven't installed this.
From 242504a103da5fc5cb868614a603710bad6a446a Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email protected]>
Date: Sat, 5 Oct 2019 02:18:45 -0700
Subject: [PATCH] =?UTF-8?q?Use=20=E2=80=9Cleast=E2=80=9D=20types=20for=20i?=
 =?UTF-8?q?ntegers=20in=20Yacc=20tables?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This changes the Yacc skeleton to use “least” integer types to
keep tables smaller on some platforms, which should lessen cache
pressure.  Since Bison uses the Yacc skeleton, it follows suit.
* data/skeletons/yacc.c (yytype_uint8, yytype_int8)
(yytype_uint16, yytype_int16): If available, use GCC predefined
macros __INT_MAX__ etc. to select a “least” type, as this avoids
namespace hassles.  Otherwise, if available (because the relevant
headers have been included) fall back on selecting a “least” type
via the C99 macros INT_MAX, INT_LEAST8_MAX, etc.  Otherwise, fall
further back on one of the builtin C99 types signed char, short,
and int.  Make sure that any selected type promotes to int.
Ignore any macros YYTYPE_INT16, YYTYPE_INT8, YYTYPE_UINT16,
YYTYPE_UINT8 defined by the user.
(yytype_uint8, yytype_uint16): Do not assume that unsigned char
and unsigned short promote to int, as this isn’t true on some
platforms (e.g., TI TMS320C55x).
* src/parse-gram.y: Include stdint.h, to help the yacc skeleton.
(YYTYPE_INT16, YYTYPE_INT8, YYTYPE_UINT16, YYTYPE_UINT8):
Remove, as these are no longer effective.
---
 data/skeletons/yacc.c | 39 +++++++++++++++++++++++++++++----------
 src/parse-gram.y      |  6 +-----
 2 files changed, 30 insertions(+), 15 deletions(-)

diff --git a/data/skeletons/yacc.c b/data/skeletons/yacc.c
index fdf4ba6d..41f22aa4 100644
--- a/data/skeletons/yacc.c
+++ b/data/skeletons/yacc.c
@@ -388,30 +388,49 @@ m4_if(b4_api_prefix, [yy], [],
 # undef short
 #endif
 
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
+/* Narrow types that promote to a signed type and that can represent a
+   signed or unsigned integer of at least N bits.  In tables they can
+   save space and decrease cache pressure.  For best results, either
+   use a compiler like GCC that predefines macros like __INT_MAX__, or
+   include limits.h and stdint.h in your grammar prolog.  */
+
+#if defined __UINT_LEAST8_MAX__ && __UINT_LEAST8_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST8_TYPE__ yytype_uint8;
+#elif defined UINT_LEAST8_MAX && defined INT_MAX && UINT_LEAST8_MAX <= INT_MAX
+typedef uint_least8_t yytype_uint8;
+#elif defined UCHAR_MAX && UCHAR_MAX <= INT_MAX
 typedef unsigned char yytype_uint8;
+#else
+typedef int yytype_uint8;
 #endif
 
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
+#if defined __INT_LEAST8_MAX__ && __INT_LEAST8_MAX__ <= __INT_MAX__
+typedef __INT_LEAST8_TYPE__ yytype_int8;
+#elif defined INT_LEAST8_MAX && defined INT_MAX && INT_LEAST8_MAX <= INT_MAX
+typedef int_least8_t yytype_int8;
 #else
 typedef signed char yytype_int8;
 #endif
 
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
+#if defined __UINT_LEAST16_MAX__ && __UINT_LEAST16_MAX__ <= __INT_MAX__
+typedef __UINT_LEAST16_TYPE__ yytype_uint16;
+#elif defined UINT_LEAST16_MAX && defined INT_MAX && UINT_LEAST16_MAX <= 
INT_MAX
+typedef uint_least16_t yytype_uint16;
+#elif defined USHRT_MAX && USHRT_MAX <= INT_MAX
 typedef unsigned short yytype_uint16;
+#else
+typedef int yytype_uint16;
 #endif
 
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
+#if defined __INT_LEAST16_MAX__ && __INT_LEAST16_MAX__ <= __INT_MAX__
+typedef __INT_LEAST16_TYPE__ yytype_int16;
+#elif defined INT_LEAST16_MAX && defined INT_MAX && INT_LEAST16_MAX <= INT_MAX
+typedef int_least16_t yytype_int16;
 #else
 typedef short yytype_int16;
 #endif
 
+
 #ifndef YYPTRDIFF_T
 # if defined __PTRDIFF_TYPE__ && defined __PTRDIFF_MAX__
 #  define YYPTRDIFF_T __PTRDIFF_TYPE__
diff --git a/src/parse-gram.y b/src/parse-gram.y
index b4132841..ab3be761 100644
--- a/src/parse-gram.y
+++ b/src/parse-gram.y
@@ -33,6 +33,7 @@
 {
   #include "system.h"
   #include <errno.h>
+  #include <stdint.h>
 
   #include "c-ctype.h"
   #include "complain.h"
@@ -112,11 +113,6 @@
   /* A string that describes a char (e.g., 'a' -> "'a'").  */
   static char const *char_name (char);
 
-  #define YYTYPE_INT16 int_fast16_t
-  #define YYTYPE_INT8 int_fast8_t
-  #define YYTYPE_UINT16 uint_fast16_t
-  #define YYTYPE_UINT8 uint_fast8_t
-
   /* Add style to semantic values in traces.  */
   static void tron (FILE *yyo);
   static void troff (FILE *yyo);
-- 
2.21.0

Reply via email to