Branch: Tag:

2014-06-24

2014-06-24 14:31:50 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Runtime: Unified struct svalue and struct fast_svalue.

Modern gcc (4.7.3) had aliasing problems with the two structs, which
caused changes performed with SET_SVAL() (which used struct fast_svalue)
to not be reflected in TYPEOF() (which used struct svalue). This in turn
caused eg casts of integers to floats to fail with "Cast failed, wanted
float, got int".

The above problem is now solved by having an actual union for the type
fields in struct svalue. This has the additional benefit of forcing
all code to use the svalue macros.

NB: This code change will cause problems with compilers that don't
support union initializers.

94:    */   struct svalue   { +  union { +  struct {    unsigned short type; /**< the data type, see PIKE_T_... */    unsigned short subtype; /**< used to store the zero type, among others */ -  +  } t; +  ptrdiff_t type_subtype; +  } tu;    union anything u; /**< contains the value */   };    - struct fast_svalue - { -  ptrdiff_t type_subtype; -  union anything u; - }; -  +    #if PIKE_BYTEORDER == 1234   #define TYPE_SUBTYPE(X,Y) ((X)|((Y)<<16))   #else   #define TYPE_SUBTYPE(X,Y) ((Y)|((X)<<16))   #endif    - #define TYPEOF(SVAL) ((SVAL).type) - #define SUBTYPEOF(SVAL) ((SVAL).subtype) + #define TYPEOF(SVAL) ((SVAL).tu.t.type) + #define SUBTYPEOF(SVAL) ((SVAL).tu.t.subtype)   #define SET_SVAL_TYPE_SUBTYPE(SVAL, TYPE, SUBTYPE) \ -  (((struct fast_svalue*)&(SVAL))->type_subtype=TYPE_SUBTYPE(TYPE,SUBTYPE)) +  ((SVAL).tu.type_subtype = TYPE_SUBTYPE(TYPE,SUBTYPE))      #define SET_SVAL_TYPE(SVAL, TYPE) (TYPEOF(SVAL) = (TYPE))   #define SET_SVAL_SUBTYPE(SVAL, TYPE) (SUBTYPEOF(SVAL) = (TYPE))
122:   #define SET_SVAL(SVAL, TYPE, SUBTYPE, FIELD, EXPR) do { \    /* Set the type afterwards to avoid a clobbered \    * svalue in case EXPR throws. */ \ -  struct fast_svalue * __sv_ptr = (struct fast_svalue *)&( SVAL ); \ +  struct svalue * __sv_ptr = &( SVAL ); \    __sv_ptr->u.FIELD = (EXPR); \ -  __sv_ptr->type_subtype = TYPE_SUBTYPE(TYPE,SUBTYPE);\ +  __sv_ptr->tu.type_subtype = TYPE_SUBTYPE(TYPE,SUBTYPE);\    } while(0)      /*
900:   /* The following macro is useful to initialize static svalues. Note    * that the value isn't always set. */   #ifdef HAVE_UNION_INIT - #define SVALUE_INIT(TYPE, SUBTYPE, VAL) {TYPE, SUBTYPE, {VAL}} - #define SVALUE_INIT_INT(VAL) {T_INT, NUMBER_NUMBER, {VAL}} - #define SVALUE_INIT_FREE {PIKE_T_FREE, NUMBER_NUMBER, {0}} + #define SVALUE_INIT(TYPE, SUBTYPE, VAL) {{{TYPE, SUBTYPE}}, {VAL}} + #define SVALUE_INIT_INT(VAL) {{{T_INT, NUMBER_NUMBER}}, {VAL}} + #define SVALUE_INIT_FREE {{{PIKE_T_FREE, NUMBER_NUMBER}}, {0}}   #else - #define SVALUE_INIT(TYPE, SUBTYPE, VAL) {TYPE, SUBTYPE} - #define SVALUE_INIT_INT(VAL) {T_INT, NUMBER_NUMBER} - #define SVALUE_INIT_FREE {PIKE_T_FREE, NUMBER_NUMBER} + #define SVALUE_INIT(TYPE, SUBTYPE, VAL) {TYPE, SUBTYPE, VAL} + #define SVALUE_INIT_INT(VAL) {T_INT, NUMBER_NUMBER, VAL} + #define SVALUE_INIT_FREE {PIKE_T_FREE, NUMBER_NUMBER, VAL}   #endif      #endif /* !SVALUE_H */