diff mbox series

[v2,06/14] make predefined_type_size() more generic

Message ID 20181212164554.43133-7-luc.vanoostenryck@gmail.com (mailing list archive)
State Superseded, archived
Headers show
Series predefined macros for intmax_t/intptr_t/... | expand

Commit Message

Luc Van Oostenryck Dec. 12, 2018, 4:45 p.m. UTC
This allows to have a single function to output the
size, the type, the maximal value, ...

Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
---
 lib.c                            | 61 ++++++++++++++++++++------------
 validation/preprocessor/predef.c |  3 ++
 2 files changed, 41 insertions(+), 23 deletions(-)

Comments

Ramsay Jones Dec. 13, 2018, 12:26 a.m. UTC | #1
On 12/12/2018 16:45, Luc Van Oostenryck wrote:
> This allows to have a single function to output the
> size, the type, the maximal value, ...
> 
> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
> ---
>  lib.c                            | 61 ++++++++++++++++++++------------
>  validation/preprocessor/predef.c |  3 ++
>  2 files changed, 41 insertions(+), 23 deletions(-)
> 
> diff --git a/lib.c b/lib.c
> index ad583da93..89126fb57 100644
> --- a/lib.c
> +++ b/lib.c
> @@ -1145,6 +1145,15 @@ static char **handle_switch(char *arg, char **next)
>  	return next;
>  }
>  
> +#define	PTYPE_SIZEOF	(1U << 0)
> +#define	PTYPE_T		(1U << 1)
> +#define	PTYPE_MAX	(1U << 2)
> +#define	PTYPE_MIN	(1U << 3)
> +#define	PTYPE_WIDTH	(1U << 4)
> +#define	PTYPE_TYPE	(1U << 5)
> +#define	PTYPE_ALL	(PTYPE_MAX|PTYPE_SIZEOF|PTYPE_WIDTH)
> +#define	PTYPE_ALL_T	(PTYPE_MAX|PTYPE_SIZEOF|PTYPE_WIDTH|PTYPE_T)
> +
>  static void predefined_sizeof(const char *name, const char *suffix, unsigned bits)
>  {
>  	char buf[32];
> @@ -1163,26 +1172,37 @@ static void predefined_width(const char *name, unsigned bits)
>  
>  static void predefined_max(const char *name, const char *suffix, unsigned bits)
>  {
> -	unsigned long long max = bits_mask(bits - 1);
> +	unsigned long long max = bits_mask(bits);
>  	char buf[32];

Hmm, this can't possibly be right, unless ...

>  
>  	snprintf(buf, sizeof(buf), "__%s_MAX__", name);
>  	predefine(buf, 1, "%#llx%s", max, suffix);
>  }
>  
> -static void predefined_type_size(const char *name, const char *suffix, unsigned bits)
> -{
> -	predefined_max(name, suffix, bits);
> -	predefined_sizeof(name, "", bits);
> -	predefined_width(name, bits);
> -}
> -
>  static void predefined_type(const char *name, struct symbol *type)
>  {
>  	const char *typename = builtin_typename(type);
>  	add_pre_buffer("#weak_define __%s_TYPE__ %s\n", name, typename);
>  }
>  
> +static void predefined_ctype(const char *name, struct symbol *type, int flags)
> +{
> +	unsigned bits = type->bit_size;
> +
> +	if (flags & PTYPE_SIZEOF) {
> +		const char *suffix = (flags & PTYPE_T) ? "_T" : "";
> +		predefined_sizeof(name, suffix, bits);
> +	}
> +	if (flags & PTYPE_MAX) {
> +		const char *suffix = builtin_type_suffix(type);
> +		predefined_max(name, suffix, bits - is_signed_type(type));

... you subtract one from the bits parameter for a signed type!

Hmm, I'm not sure I like this. I had expected something like:

static void predefined_max(const char *name, struct symbol *type)
{
	unsigned bits = type->bit_size;
	const char *suffix = builtin_type_suffix(type);
        unsigned long long max;
        char buf[32];

	if (is_signed_type(type))
		bits = bits - 1;
	max = bits_mask(bits);
        snprintf(buf, sizeof(buf), "__%s_MAX__", name);
        predefine(buf, 1, "%#llx%s", max, suffix);
}

... or something like that. (but it is your call ;-) ).

BTW, I haven't finished testing (something else came up), but
some platforms are using the 'long' type for wchar_t. (Also, I
suspect some of the tests won't work ...) Oh, also, there seems
to be a discrepancy in the size of 'long double'.

[I will try to finish testing tomorrow]

Thanks!

ATB,
Ramsay Jones


> +	}
> +	if (flags & PTYPE_TYPE)
> +		predefined_type(name, type);
> +	if (flags & PTYPE_WIDTH)
> +		predefined_width(name, bits);
> +}
> +
>  static void predefined_macros(void)
>  {
>  	predefine("__CHECKER__", 0, "1");
> @@ -1224,27 +1244,24 @@ static void predefined_macros(void)
>  		break;
>  	}
>  
> -	predefined_sizeof("SHORT", "", bits_in_short);
> -	predefined_max("SHRT", "", bits_in_short);
> -	predefined_width("SHRT",   bits_in_short);
> -	predefined_max("SCHAR", "", bits_in_char);
> -	predefined_width("SCHAR",   bits_in_char);
>  	predefined_sizeof("WCHAR", "_T", bits_in_wchar);
>  	predefined_max("WCHAR", "", bits_in_wchar);
>  	predefined_width("WCHAR",   bits_in_wchar);
>  	predefine("__CHAR_BIT__", 1, "%d", bits_in_char);
>  
> -	predefined_type_size("INT", "", bits_in_int);
> -	predefined_type_size("LONG", "L", bits_in_long);
> -	predefined_type_size("LONG_LONG", "LL", bits_in_longlong);
> +	predefined_ctype("SHORT",     &short_ctype, PTYPE_SIZEOF);
> +	predefined_ctype("SHRT",      &short_ctype, PTYPE_MAX|PTYPE_WIDTH);
> +	predefined_ctype("SCHAR",      &char_ctype, PTYPE_MAX|PTYPE_WIDTH);
> +
> +	predefined_ctype("INT",         &int_ctype, PTYPE_ALL);
> +	predefined_ctype("LONG",       &long_ctype, PTYPE_ALL);
> +	predefined_ctype("LONG_LONG", &llong_ctype, PTYPE_ALL);
>  
>  	predefined_sizeof("INT128", "", 128);
>  
> -	predefined_sizeof("SIZE", "_T", bits_in_pointer);
> -	predefined_width( "SIZE",   bits_in_pointer);
> -	predefined_sizeof("PTRDIFF", "_T", bits_in_pointer);
> -	predefined_width( "PTRDIFF",   bits_in_pointer);
> -	predefined_sizeof("POINTER", "", bits_in_pointer);
> +	predefined_ctype("PTRDIFF",  ssize_t_ctype, PTYPE_ALL_T|PTYPE_TYPE);
> +	predefined_ctype("SIZE",      size_t_ctype, PTYPE_ALL_T|PTYPE_TYPE);
> +	predefined_ctype("POINTER",     &ptr_ctype, PTYPE_SIZEOF);
>  
>  	predefined_sizeof("FLOAT", "", bits_in_float);
>  	predefined_sizeof("DOUBLE", "", bits_in_double);
> @@ -1276,8 +1293,6 @@ static void create_builtin_stream(void)
>  	// Temporary hack
>  	add_pre_buffer("#define _Pragma(x)\n");
>  
> -	predefined_type("SIZE", size_t_ctype);
> -
>  	/* add the multiarch include directories, if any */
>  	if (multiarch_dir && *multiarch_dir) {
>  		add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir);
> diff --git a/validation/preprocessor/predef.c b/validation/preprocessor/predef.c
> index ccb5d3619..298bdd93c 100644
> --- a/validation/preprocessor/predef.c
> +++ b/validation/preprocessor/predef.c
> @@ -17,6 +17,8 @@ int test(void)
>  	TEST_SMAX(INT, int);
>  	TEST_SMAX(LONG, long);
>  	TEST_SMAX(LONG_LONG, long long);
> +	TEST_SMAX(PTRDIFF, __PTRDIFF_TYPE__);
> +	TEST_UMAX(SIZE, __SIZE_TYPE__);
>  
>  #define TEST_SIZEOF(X, T) if (__SIZEOF_ ## X ## __ != sizeof(T)) return 1
>  	TEST_SIZEOF(SHORT, short);
> @@ -24,6 +26,7 @@ int test(void)
>  	TEST_SIZEOF(LONG, long);
>  	TEST_SIZEOF(LONG_LONG, long long);
>  	TEST_SIZEOF(INT128, __int128);
> +	TEST_SIZEOF(PTRDIFF_T, __PTRDIFF_TYPE__);
>  	TEST_SIZEOF(SIZE_T, __SIZE_TYPE__);
>  	TEST_SIZEOF(POINTER, void*);
>  	TEST_SIZEOF(FLOAT, float);
>
Luc Van Oostenryck Dec. 13, 2018, 1:36 a.m. UTC | #2
On Thu, Dec 13, 2018 at 12:26:50AM +0000, Ramsay Jones wrote:
> On 12/12/2018 16:45, Luc Van Oostenryck wrote:
> >  static void predefined_max(const char *name, const char *suffix, unsigned bits)
> >  {
> > -	unsigned long long max = bits_mask(bits - 1);
> > +	unsigned long long max = bits_mask(bits);
> >  	char buf[32];
> 
> Hmm, this can't possibly be right, unless ...

...
 
> > +	if (flags & PTYPE_MAX) {
> > +		const char *suffix = builtin_type_suffix(type);
> > +		predefined_max(name, suffix, bits - is_signed_type(type));
> 
> ... you subtract one from the bits parameter for a signed type!
> 
> Hmm, I'm not sure I like this. I had expected something like:
> 
> static void predefined_max(const char *name, struct symbol *type)
> {
> 	unsigned bits = type->bit_size;
> 	const char *suffix = builtin_type_suffix(type);
>         unsigned long long max;
>         char buf[32];
> 
> 	if (is_signed_type(type))
> 		bits = bits - 1;
> 	max = bits_mask(bits);
>         snprintf(buf, sizeof(buf), "__%s_MAX__", name);
>         predefine(buf, 1, "%#llx%s", max, suffix);
> }
>
> ... or something like that. (but it is your call ;-) ).
> 

Absolutely, but this can't be done at in this patch because
the predefined_max() with an explicit number of bits is still
needed for wchar which receive a type only in the next patch
(and I switching the patch order bring others complications
with wchar).

I'll fix it in one of the subsequent patches.

-- Luc
 
> BTW, I haven't finished testing (something else came up), but
> some platforms are using the 'long' type for wchar_t. (Also, I
> suspect some of the tests won't work ...) Oh, also, there seems
> to be a discrepancy in the size of 'long double'.
> 
> [I will try to finish testing tomorrow]
> 
> Thanks!

Thanks to you for the testing!

For the platforms using long for wchar_t, yes, it's the same kind
of mess as for int32_t. I really don't like these #ifdeferies
(like currently done for int32_t). Of course, having the default
correct for the native platform is the minimal but ...
It's really a nasty problem since there is a lot of flags
that can modify these types (I'm thinking at -mlong-double-64
on x86, -mabi=... on ARM & MIPS, ...) plus the fact that it
is OS dependent.

-- Luc
diff mbox series

Patch

diff --git a/lib.c b/lib.c
index ad583da93..89126fb57 100644
--- a/lib.c
+++ b/lib.c
@@ -1145,6 +1145,15 @@  static char **handle_switch(char *arg, char **next)
 	return next;
 }
 
+#define	PTYPE_SIZEOF	(1U << 0)
+#define	PTYPE_T		(1U << 1)
+#define	PTYPE_MAX	(1U << 2)
+#define	PTYPE_MIN	(1U << 3)
+#define	PTYPE_WIDTH	(1U << 4)
+#define	PTYPE_TYPE	(1U << 5)
+#define	PTYPE_ALL	(PTYPE_MAX|PTYPE_SIZEOF|PTYPE_WIDTH)
+#define	PTYPE_ALL_T	(PTYPE_MAX|PTYPE_SIZEOF|PTYPE_WIDTH|PTYPE_T)
+
 static void predefined_sizeof(const char *name, const char *suffix, unsigned bits)
 {
 	char buf[32];
@@ -1163,26 +1172,37 @@  static void predefined_width(const char *name, unsigned bits)
 
 static void predefined_max(const char *name, const char *suffix, unsigned bits)
 {
-	unsigned long long max = bits_mask(bits - 1);
+	unsigned long long max = bits_mask(bits);
 	char buf[32];
 
 	snprintf(buf, sizeof(buf), "__%s_MAX__", name);
 	predefine(buf, 1, "%#llx%s", max, suffix);
 }
 
-static void predefined_type_size(const char *name, const char *suffix, unsigned bits)
-{
-	predefined_max(name, suffix, bits);
-	predefined_sizeof(name, "", bits);
-	predefined_width(name, bits);
-}
-
 static void predefined_type(const char *name, struct symbol *type)
 {
 	const char *typename = builtin_typename(type);
 	add_pre_buffer("#weak_define __%s_TYPE__ %s\n", name, typename);
 }
 
+static void predefined_ctype(const char *name, struct symbol *type, int flags)
+{
+	unsigned bits = type->bit_size;
+
+	if (flags & PTYPE_SIZEOF) {
+		const char *suffix = (flags & PTYPE_T) ? "_T" : "";
+		predefined_sizeof(name, suffix, bits);
+	}
+	if (flags & PTYPE_MAX) {
+		const char *suffix = builtin_type_suffix(type);
+		predefined_max(name, suffix, bits - is_signed_type(type));
+	}
+	if (flags & PTYPE_TYPE)
+		predefined_type(name, type);
+	if (flags & PTYPE_WIDTH)
+		predefined_width(name, bits);
+}
+
 static void predefined_macros(void)
 {
 	predefine("__CHECKER__", 0, "1");
@@ -1224,27 +1244,24 @@  static void predefined_macros(void)
 		break;
 	}
 
-	predefined_sizeof("SHORT", "", bits_in_short);
-	predefined_max("SHRT", "", bits_in_short);
-	predefined_width("SHRT",   bits_in_short);
-	predefined_max("SCHAR", "", bits_in_char);
-	predefined_width("SCHAR",   bits_in_char);
 	predefined_sizeof("WCHAR", "_T", bits_in_wchar);
 	predefined_max("WCHAR", "", bits_in_wchar);
 	predefined_width("WCHAR",   bits_in_wchar);
 	predefine("__CHAR_BIT__", 1, "%d", bits_in_char);
 
-	predefined_type_size("INT", "", bits_in_int);
-	predefined_type_size("LONG", "L", bits_in_long);
-	predefined_type_size("LONG_LONG", "LL", bits_in_longlong);
+	predefined_ctype("SHORT",     &short_ctype, PTYPE_SIZEOF);
+	predefined_ctype("SHRT",      &short_ctype, PTYPE_MAX|PTYPE_WIDTH);
+	predefined_ctype("SCHAR",      &char_ctype, PTYPE_MAX|PTYPE_WIDTH);
+
+	predefined_ctype("INT",         &int_ctype, PTYPE_ALL);
+	predefined_ctype("LONG",       &long_ctype, PTYPE_ALL);
+	predefined_ctype("LONG_LONG", &llong_ctype, PTYPE_ALL);
 
 	predefined_sizeof("INT128", "", 128);
 
-	predefined_sizeof("SIZE", "_T", bits_in_pointer);
-	predefined_width( "SIZE",   bits_in_pointer);
-	predefined_sizeof("PTRDIFF", "_T", bits_in_pointer);
-	predefined_width( "PTRDIFF",   bits_in_pointer);
-	predefined_sizeof("POINTER", "", bits_in_pointer);
+	predefined_ctype("PTRDIFF",  ssize_t_ctype, PTYPE_ALL_T|PTYPE_TYPE);
+	predefined_ctype("SIZE",      size_t_ctype, PTYPE_ALL_T|PTYPE_TYPE);
+	predefined_ctype("POINTER",     &ptr_ctype, PTYPE_SIZEOF);
 
 	predefined_sizeof("FLOAT", "", bits_in_float);
 	predefined_sizeof("DOUBLE", "", bits_in_double);
@@ -1276,8 +1293,6 @@  static void create_builtin_stream(void)
 	// Temporary hack
 	add_pre_buffer("#define _Pragma(x)\n");
 
-	predefined_type("SIZE", size_t_ctype);
-
 	/* add the multiarch include directories, if any */
 	if (multiarch_dir && *multiarch_dir) {
 		add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir);
diff --git a/validation/preprocessor/predef.c b/validation/preprocessor/predef.c
index ccb5d3619..298bdd93c 100644
--- a/validation/preprocessor/predef.c
+++ b/validation/preprocessor/predef.c
@@ -17,6 +17,8 @@  int test(void)
 	TEST_SMAX(INT, int);
 	TEST_SMAX(LONG, long);
 	TEST_SMAX(LONG_LONG, long long);
+	TEST_SMAX(PTRDIFF, __PTRDIFF_TYPE__);
+	TEST_UMAX(SIZE, __SIZE_TYPE__);
 
 #define TEST_SIZEOF(X, T) if (__SIZEOF_ ## X ## __ != sizeof(T)) return 1
 	TEST_SIZEOF(SHORT, short);
@@ -24,6 +26,7 @@  int test(void)
 	TEST_SIZEOF(LONG, long);
 	TEST_SIZEOF(LONG_LONG, long long);
 	TEST_SIZEOF(INT128, __int128);
+	TEST_SIZEOF(PTRDIFF_T, __PTRDIFF_TYPE__);
 	TEST_SIZEOF(SIZE_T, __SIZE_TYPE__);
 	TEST_SIZEOF(POINTER, void*);
 	TEST_SIZEOF(FLOAT, float);