From 75917d62434b103a89fc65bde66a1a3e97b598a1 Mon Sep 17 00:00:00 2001 From: Andy Wingo Date: Thu, 15 Sep 2011 12:28:03 -0700 Subject: [PATCH] Revert "SCM is either a union or scm_t_bits" This reverts commit 80125469ef95f6d8d46a26619fb2f85151f32719. Conflicts: libguile/__scm.h --- libguile/__scm.h | 25 +++++++++++++++++++++ libguile/tags.h | 56 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/libguile/__scm.h b/libguile/__scm.h index 3a8b07a6f..ee73855c6 100644 --- a/libguile/__scm.h +++ b/libguile/__scm.h @@ -273,6 +273,31 @@ #define SCM_DEBUG_REST_ARGUMENT SCM_DEBUG #endif +/* The macro SCM_DEBUG_TYPING_STRICTNESS indicates what level of type checking + * shall be performed with respect to the use of the SCM datatype. The macro + * may be defined to one of the values 0, 1 and 2. + * + * A value of 0 means that there will be no compile time type checking, since + * the SCM datatype will be declared as an integral type. This setting should + * only be used on systems, where casting from integral types to pointers may + * lead to loss of bit information. + * + * A value of 1 means that there will an intermediate level of compile time + * type checking, since the SCM datatype will be declared as a pointer to an + * undefined struct. This setting is the default, since it does not cost + * anything in terms of performance or code size. + * + * A value of 2 provides a maximum level of compile time type checking since + * the SCM datatype will be declared as a struct. This setting should be used + * for _compile time_ type checking only, since the compiled result is likely + * to be quite inefficient. The right way to make use of this option is to do + * a 'make clean; make CFLAGS=-DSCM_DEBUG_TYPING_STRICTNESS=2', fix your + * errors, and then do 'make clean; make'. + */ +#ifndef SCM_DEBUG_TYPING_STRICTNESS +#define SCM_DEBUG_TYPING_STRICTNESS 1 +#endif + /* {Feature Options} diff --git a/libguile/tags.h b/libguile/tags.h index c03f43dfe..35b5d17c2 100644 --- a/libguile/tags.h +++ b/libguile/tags.h @@ -61,6 +61,7 @@ /* For dealing with the bit level representation of scheme objects we define * scm_t_bits: */ + typedef scm_t_intptr scm_t_signed_bits; typedef scm_t_uintptr scm_t_bits; @@ -69,28 +70,47 @@ typedef scm_t_uintptr scm_t_bits; #define SCM_T_BITS_MAX SCM_T_UINTPTR_MAX -/* But as external interface, we pack the bits in a union. This makes - * the compiler treat SCM values as a disjoint type, allowing the - * detection of many common errors. +/* But as external interface, we define SCM, which may, according to the + * desired level of type checking, be defined in several ways: */ -union SCM -{ - scm_t_bits n; -}; +#if (SCM_DEBUG_TYPING_STRICTNESS == 2) +typedef union SCM { scm_t_bits n; } SCM; +# define SCM_UNPACK(x) ((x).n) +# define SCM_PACK(x) ((SCM) { (scm_t_bits) (x) }) +#elif (SCM_DEBUG_TYPING_STRICTNESS == 1) +/* This is the default, which provides an intermediate level of compile time + * type checking while still resulting in very efficient code. + */ + typedef struct scm_unused_struct { char scm_unused_field; } *SCM; -#ifndef SCM_USING_PREHISTORIC_COMPILER -/* With GCC at least, wrapping the bits in a union provides no - * performance penalty. - */ -typedef union SCM SCM; -#define SCM_UNPACK(x) ((x).n) -#define SCM_PACK(x) ((SCM) { (scm_t_bits) (x) }) +/* + The 0?: constructions makes sure that the code is never executed, + and that there is no performance hit. However, the alternative is + compiled, and does generate a warning when used with the wrong + pointer type. + + The Tru64 and ia64-hp-hpux11.23 compilers fail on `case (0?0=0:x)' + statements, so for them type-checking is disabled. */ +#if defined __DECC || defined __HP_cc +# define SCM_UNPACK(x) ((scm_t_bits) (x)) #else -/* But we do provide an escape valve for less capable compilers. +# define SCM_UNPACK(x) ((scm_t_bits) (0? (*(SCM*)0=(x)): x)) +#endif + +/* + There is no typechecking on SCM_PACK, since all kinds of types + (unsigned long, void*) go in SCM_PACK */ -typedef scm_t_bits SCM; -#define SCM_UNPACK(x) (x) -#define SCM_PACK(x) ((SCM) (x)) +# define SCM_PACK(x) ((SCM) (x)) + +#else +/* This should be used as a fall back solution for machines on which casting + * to a pointer may lead to loss of bit information, e. g. in the three least + * significant bits. + */ + typedef scm_t_bits SCM; +# define SCM_UNPACK(x) (x) +# define SCM_PACK(x) ((SCM) (x)) #endif