1 /*******************************************************************************
2 *
3 * MODULE: layout.c
4 *
5 ********************************************************************************
6 *
7 * DESCRIPTION: Type layouting routines
8 *
9 ********************************************************************************
10 *
11 * Copyright (c) 2002-2020 Marcus Holland-Moritz. All rights reserved.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the same terms as Perl itself.
14 *
15 *******************************************************************************/
16 
17 /*===== GLOBAL INCLUDES ======================================================*/
18 
19 #include <assert.h>
20 #include <stddef.h>
21 
22 
23 /*===== LOCAL INCLUDES =======================================================*/
24 
25 #include "ctlib/ctdebug.h"
26 #include "ctlib/cterror.h"
27 #include "ctlib/layout.h"
28 
29 
30 /*===== DEFINES ==============================================================*/
31 
32 #define LAYOUT_ALIGNMENT(pLP)  ((pLP)->alignment ? (pLP)->alignment            \
33                                                  : CTLIB_ALIGNMENT)
34 
35 #define LAYOUT_COMPOUND_ALIGNMENT(pLP)  ((pLP)->compound_alignment             \
36                                          ? (pLP)->compound_alignment           \
37                                          : CTLIB_COMPOUND_ALIGNMENT)
38 
39 
40 /*===== TYPEDEFS =============================================================*/
41 
42 /*===== STATIC FUNCTION PROTOTYPES ===========================================*/
43 
44 /*===== EXTERNAL VARIABLES ===================================================*/
45 
46 unsigned native_alignment          = 0;
47 unsigned native_compound_alignment = 0;
48 
49 
50 /*===== GLOBAL VARIABLES =====================================================*/
51 
52 /*===== STATIC VARIABLES =====================================================*/
53 
54 /*===== STATIC FUNCTIONS =====================================================*/
55 
56 /*******************************************************************************
57 *
58 *   ROUTINE: get_type_info_generic
59 *
60 *   WRITTEN BY: Marcus Holland-Moritz             ON: Jan 2002
61 *   CHANGED BY:                                   ON:
62 *
63 ********************************************************************************
64 *
65 * DESCRIPTION:
66 *
67 *   ARGUMENTS:
68 *
69 *     RETURNS:
70 *
71 *******************************************************************************/
72 
get_type_info_generic(const LayoutParam * pLP,const TypeSpec * pTS,const Declarator * pDecl,const char * format,...)73 ErrorGTI get_type_info_generic(const LayoutParam *pLP, const TypeSpec *pTS,
74                                const Declarator *pDecl, const char *format, ...)
75 {
76   u_32 flags = pTS->tflags;
77   void *tptr = pTS->ptr;
78   unsigned *pSize = NULL, *pItemSize = NULL, *pAlign = NULL;
79   u_32 *pFlags = NULL;
80   ErrorGTI err = GTI_NO_ERROR;
81   unsigned size;
82   va_list ap;
83 
84   CT_DEBUG(CTLIB, ("get_type_info_generic( pLP=%p, pTS=%p "
85                    "[flags=0x%08lX, ptr=%p], pDecl=%p, format=\"%s\" )",
86                    pLP, pTS, (unsigned long) flags, tptr, pDecl, format));
87 
88   va_start(ap, format);
89 
90   for (; *format; format++)
91   {
92     switch (*format)
93     {
94       case 'a': pAlign    = va_arg(ap, unsigned *); break;
95       case 'f': pFlags    = va_arg(ap, u_32 *);     break;
96       case 'i': pItemSize = va_arg(ap, unsigned *); break;
97       case 's': pSize     = va_arg(ap, unsigned *); break;
98 
99       default:
100         fatal_error("invalid format character (%c) in get_type_info_generic()", *format);
101         break;
102     }
103   }
104 
105   va_end(ap);
106 
107   if (pFlags)
108     *pFlags = 0;
109 
110   if (pDecl && pDecl->pointer_flag)
111   {
112     CT_DEBUG(CTLIB, ("pointer flag set"));
113 
114     size = pLP->ptr_size ? pLP->ptr_size : CTLIB_POINTER_SIZE;
115 
116     if (pAlign)
117       *pAlign = size;
118   }
119   else if (flags & T_TYPE)
120   {
121     Typedef *pTypedef = (Typedef *) tptr;
122 
123     CT_DEBUG(CTLIB, ("T_TYPE flag set"));
124 
125     assert(pTypedef != NULL);
126 
127     if (pFlags)
128     {
129       u_32 flags;
130 
131       err = get_type_info_generic(pLP, pTypedef->pType, pTypedef->pDecl,
132                                   "saf", &size, pAlign, &flags);
133 
134       *pFlags |= flags;
135     }
136     else
137       err = get_type_info_generic(pLP, pTypedef->pType, pTypedef->pDecl,
138                                   "sa", &size, pAlign);
139   }
140   else if (flags & T_ENUM)
141   {
142     CT_DEBUG(CTLIB, ("T_ENUM flag set"));
143 
144     assert(pLP->enum_size > 0 || tptr != NULL);
145 
146     size = pLP->enum_size > 0
147            ? (unsigned) pLP->enum_size
148            : ((EnumSpecifier *) tptr)->sizes[-pLP->enum_size];
149 
150     if (pAlign)
151       *pAlign = size;
152   }
153   else if (flags & T_COMPOUND)
154   {
155     Struct *pStruct = (Struct *) tptr;
156 
157     CT_DEBUG(CTLIB, ("T_STRUCT or T_UNION flag set"));
158 
159     assert(pStruct != NULL);
160 
161     if (pStruct->declarations == NULL)
162     {
163       CT_DEBUG(CTLIB, ("no struct declarations in get_type_info_generic"));
164 
165       size = pLP->int_size ? pLP->int_size : sizeof(int);
166 
167       if( pAlign )
168         *pAlign = size;
169 
170       err = GTI_NO_STRUCT_DECL;
171     }
172     else
173     {
174       if (pStruct->align == 0)
175         layout_compound_generic(pLP, pStruct);
176 
177       size = pStruct->size;
178 
179       if (pAlign)
180         *pAlign = pStruct->align;
181     }
182 
183     if (pFlags)
184       *pFlags |= pStruct->tflags & (T_HASBITFIELD | T_UNSAFE_VAL);
185   }
186   else
187   {
188     CT_DEBUG( CTLIB, ("only basic type flags set") );
189 
190 #define LOAD_SIZE( type ) \
191         size = pLP->type ## _size ? pLP->type ## _size : CTLIB_ ## type ## _SIZE
192 
193     if (flags & T_VOID)  /* XXX: do we want void ? */
194       size = 1;
195     else if ((flags & (T_LONG|T_DOUBLE)) == (T_LONG|T_DOUBLE))
196       LOAD_SIZE(long_double);
197     else if(flags & T_LONGLONG) LOAD_SIZE(long_long);
198     else if(flags & T_FLOAT)    LOAD_SIZE(float);
199     else if(flags & T_DOUBLE)   LOAD_SIZE(double);
200     else if(flags & T_CHAR)     LOAD_SIZE(char);
201     else if(flags & T_SHORT)    LOAD_SIZE(short);
202     else if(flags & T_LONG)     LOAD_SIZE(long);
203     else                        LOAD_SIZE(int);
204 
205 #undef LOAD_SIZE
206 
207     if (pAlign)
208       *pAlign = size;
209   }
210 
211   if (pItemSize)
212     *pItemSize = size;
213 
214   if (pSize)
215   {
216     if (pDecl && pDecl->array_flag)
217     {
218       if (pDecl->array_flag)
219       {
220         ListIterator ai;
221         Value *pValue;
222 
223         CT_DEBUG(CTLIB, ("processing array [%p]", pDecl->ext.array));
224 
225         LL_foreach(pValue, ai, pDecl->ext.array)
226         {
227           CT_DEBUG(CTLIB, ("[%ld]", pValue->iv));
228 
229           size *= pValue->iv;
230 
231           if (pFlags && IS_UNSAFE_VAL(*pValue))
232             *pFlags |= T_UNSAFE_VAL;
233         }
234       }
235       else if (pDecl->bitfield_flag)
236       {
237         size = 0;
238       }
239     }
240 
241     *pSize = size;
242   }
243 
244   CT_DEBUG(CTLIB, ("get_type_info_generic( size(%p)=%d, align(%p)=%d, "
245                    "item(%p)=%d, flags(%p)=0x%08lX ) finished",
246                    pSize, pSize ? *pSize : 0, pAlign, pAlign ? *pAlign : 0,
247                    pItemSize, pItemSize ? *pItemSize : 0,
248                    pFlags, (unsigned long) (pFlags ? *pFlags : 0)));
249 
250   return err;
251 }
252 
253 /*******************************************************************************
254 *
255 *   ROUTINE: layout_compound_generic
256 *
257 *   WRITTEN BY: Marcus Holland-Moritz             ON: Jan 2002
258 *   CHANGED BY:                                   ON:
259 *
260 ********************************************************************************
261 *
262 * DESCRIPTION:
263 *
264 *   ARGUMENTS:
265 *
266 *     RETURNS:
267 *
268 *******************************************************************************/
269 
270 #define BL_SET_BYTE_ORDER(byte_order)                                          \
271         do {                                                                   \
272           BLPropValue pv;                                                      \
273           enum BLError error;                                                  \
274           switch (byte_order)                                                  \
275           {                                                                    \
276             case CBO_BIG_ENDIAN:    pv.v.v_str = BLPV_BIG_ENDIAN;    break;    \
277             case CBO_LITTLE_ENDIAN: pv.v.v_str = BLPV_LITTLE_ENDIAN; break;    \
278             default:                                                           \
279               fatal_error("invalid byte-order in BL_SET_BYTEORDER()");         \
280               break;                                                           \
281           }                                                                    \
282           pv.type = BLPVT_STR;                                                 \
283           error = bl->m->set(bl, BLP_BYTE_ORDER, &pv);                         \
284           if (error != BLE_NO_ERROR)                                           \
285             fatal_error(blproperror, 's', BLP_BYTE_ORDER, error);              \
286         } while (0)
287 
288 #define BL_SET(prop, val)                                                      \
289         do {                                                                   \
290           BLPropValue pv;                                                      \
291           enum BLError error;                                                  \
292           pv.type = BLPVT_INT;                                                 \
293           pv.v.v_int = val;                                                    \
294           error = bl->m->set(bl, BLP_ ## prop, &pv);                           \
295           if (error != BLE_NO_ERROR)                                           \
296             fatal_error(blproperror, 's', BLP_ ## prop, error);                \
297         } while (0)
298 
299 #define BL_GET(prop, val)                                                      \
300         do {                                                                   \
301           BLPropValue pv;                                                      \
302           enum BLError error;                                                  \
303           error = bl->m->get(bl, BLP_ ## prop, &pv);                           \
304           if (error != BLE_NO_ERROR)                                           \
305             fatal_error(blproperror, 'g', BLP_ ## prop, error);                \
306           assert(pv.type == BLPVT_INT);                                        \
307           val = pv.v.v_int;                                                    \
308         } while (0)
309 
310 #define FINISH_BITFIELD                                                        \
311         do {                                                                   \
312           bl->m->finalize(bl);                                                 \
313           BL_GET(OFFSET, pStruct->size );                                      \
314           BL_GET(ALIGN,  pStruct->align);                                      \
315         } while (0)
316 
layout_compound_generic(const LayoutParam * pLP,Struct * pStruct)317 void layout_compound_generic(const LayoutParam *pLP, Struct *pStruct)
318 {
319   ListIterator       sdi;
320   static const char *blproperror = "couldn't %cet bitfield layouter property (%d) => error %d";
321   StructDeclaration *pStructDecl;
322   Declarator        *pDecl;
323   unsigned           size, item_size, align, alignment;
324   u_32               flags;
325   int                in_bitfield = 0;
326   BitfieldLayouter   bl = pLP->bflayouter;
327 
328   CT_DEBUG(CTLIB, ("layout_compound_generic( %s ), got %d struct declaration(s)",
329            pStruct->identifier[0] ? pStruct->identifier : "<no-identifier>",
330            LL_count(pStruct->declarations)));
331 
332   if (pStruct->declarations == NULL)
333   {
334     CT_DEBUG(CTLIB, ("no struct declarations in layout_compound_generic"));
335     return;
336   }
337 
338   alignment = pStruct->pack ? pStruct->pack : LAYOUT_ALIGNMENT(pLP);
339 
340   pStruct->align = alignment < LAYOUT_COMPOUND_ALIGNMENT(pLP)
341                  ? alignment : LAYOUT_COMPOUND_ALIGNMENT(pLP);
342 
343   BL_SET(MAX_ALIGN, alignment);
344   BL_SET_BYTE_ORDER(pLP->byte_order);
345 
346   LL_foreach(pStructDecl, sdi, pStruct->declarations)
347   {
348     CT_DEBUG(CTLIB, ("%d declarators in struct declaration, tflags=0x%08lX ptr=%p",
349              LL_count(pStructDecl->declarators),
350              (unsigned long) pStructDecl->type.tflags, pStructDecl->type.ptr));
351 
352     pStructDecl->offset = pStruct->tflags & T_STRUCT ? -1 : 0;
353     pStructDecl->size   = 0;
354 
355     if (pStructDecl->declarators)
356     {
357       ListIterator di;
358 
359       LL_foreach(pDecl, di, pStructDecl->declarators)
360       {
361         CT_DEBUG(CTLIB, ("current declarator [%s]",
362                  pDecl->identifier[0] ? pDecl->identifier : "<no-identifier>"));
363 
364         get_type_info_generic(pLP, &pStructDecl->type, pDecl,
365                               "saif", &size, &align, &item_size, &flags);
366 
367         CT_DEBUG(CTLIB, ("declarator size=%u, item=%u, align=%u, flags=0x%08lX",
368                          size, item_size, align, (unsigned long) flags));
369 
370         if ((flags & T_HASBITFIELD) || pDecl->bitfield_flag)
371         {
372           CT_DEBUG(CTLIB, ("found bitfield '%s' in '%s %s'",
373                    pDecl->identifier[0] ? pDecl->identifier : "<no-identifier>",
374                    pStruct->tflags & T_STRUCT ? "struct" : "union",
375                    pStruct->identifier[0] ? pStruct->identifier : "<no-identifier>"));
376 
377           pStruct->tflags |= T_HASBITFIELD;
378         }
379 
380         if (flags & T_UNSAFE_VAL)
381         {
382           CT_DEBUG(CTLIB, ("unsafe values in '%s %s'",
383                    pStruct->tflags & T_STRUCT ? "struct" : "union",
384                    pStruct->identifier[0] ? pStruct->identifier : "<no-identifier>"));
385 
386           pStruct->tflags |= T_UNSAFE_VAL;
387         }
388 
389         if (pDecl->bitfield_flag)
390         {
391           BLPushParam pp;
392           enum BLError error;
393 
394           if (!in_bitfield)
395           {
396             bl->m->reset(bl);
397 
398             BL_SET(ALIGN, pStruct->align);
399 
400             if (pStruct->tflags & T_STRUCT)
401             {
402               BL_SET(OFFSET, pStruct->size);
403               in_bitfield = 1;
404             }
405             else /* T_UNION */
406             {
407               BL_SET(OFFSET, 0);
408               /* don't set in_bitfield = 1 */
409             }
410           }
411 
412           pp.pStruct    = pStruct;
413           pp.pDecl      = pDecl;
414           pp.type_size  = item_size;
415           pp.type_align = align;
416 
417           error = bl->m->push(bl, &pp);
418 
419           if (error != BLE_NO_ERROR)
420             fatal_error("couldn't push bitfield => error %d", error);
421 
422           if (pStruct->tflags & T_UNION)
423             FINISH_BITFIELD;
424         }
425         else
426         {
427           if (in_bitfield)
428           {
429             FINISH_BITFIELD;
430             in_bitfield = 0;
431           }
432 
433           pDecl->size      = size;
434           pDecl->item_size = item_size;
435 
436           if (align > alignment)
437             align = alignment;
438 
439           if (align > pStruct->align)
440             pStruct->align = align;
441 
442           if (pStruct->tflags & T_STRUCT)
443           {
444             unsigned mod = pStruct->size % align;
445 
446             if (mod)
447               pStruct->size += align - mod;
448 
449             if (pStructDecl->offset < 0)
450               pStructDecl->offset = pStruct->size;
451 
452             pDecl->offset = pStruct->size;
453             pStruct->size += size;
454           }
455           else /* T_UNION */
456           {
457             pDecl->offset = 0;
458 
459             if (size > pStruct->size)
460               pStruct->size = size;
461           }
462         }
463       }
464     }
465     else /* unnamed struct/union */
466     {
467       if (in_bitfield)
468       {
469         FINISH_BITFIELD;
470         in_bitfield = 0;
471       }
472 
473       CT_DEBUG(CTLIB, ("current declaration is an unnamed struct/union"));
474 
475       get_type_info_generic(pLP, &pStructDecl->type, NULL,
476                             "saf", &size, &align, &flags);
477       CT_DEBUG(CTLIB, ("unnamed struct/union: size=%d, align=%d, flags=0x%08lX",
478                        size, align, (unsigned long) flags));
479 
480       if (flags & T_HASBITFIELD)
481       {
482         CT_DEBUG(CTLIB, ("found bitfield in unnamed struct/union"));
483         pStruct->tflags |= T_HASBITFIELD;
484       }
485 
486       if (flags & T_UNSAFE_VAL)
487       {
488         CT_DEBUG(CTLIB, ("unsafe values in unnamed struct/union"));
489         pStruct->tflags |= T_UNSAFE_VAL;
490       }
491 
492       if (align > alignment)
493         align = alignment;
494 
495       if (align > pStruct->align)
496         pStruct->align = align;
497 
498       if (pStruct->tflags & T_STRUCT)
499       {
500         unsigned mod = pStruct->size % align;
501 
502         if (mod)
503           pStruct->size += align - mod;
504 
505         if (pStructDecl->offset < 0)
506           pStructDecl->offset = pStruct->size;
507 
508         pStruct->size += size;
509       }
510       else /* T_UNION */
511       {
512         if (size > pStruct->size)
513           pStruct->size = size;
514       }
515     }
516 
517     if (pStructDecl->offset < 0)
518       pStructDecl->offset = pStruct->size;
519 
520     pStructDecl->size = pStruct->size - pStructDecl->offset;
521 
522   }
523 
524   if (in_bitfield)
525     FINISH_BITFIELD;
526 
527   if (pStruct->size % pStruct->align)
528     pStruct->size += pStruct->align - pStruct->size % pStruct->align;
529 
530   CT_DEBUG(CTLIB, ("layout_compound_generic( %s ): size=%d, align=%d",
531            pStruct->identifier[0] ? pStruct->identifier : "<no-identifier>",
532            pStruct->size, pStruct->align));
533 }
534 
535 /*******************************************************************************
536 *
537 *   ROUTINE: get_native_alignment
538 *
539 *   WRITTEN BY: Marcus Holland-Moritz             ON: Aug 2004
540 *   CHANGED BY:                                   ON:
541 *
542 ********************************************************************************
543 *
544 * DESCRIPTION: Determine the native struct member alignment and store it to
545 *              the global native_alignment.
546 *
547 *   ARGUMENTS:
548 *
549 *     RETURNS:
550 *
551 *******************************************************************************/
552 
553 #define CHECK_NATIVE_ALIGNMENT(type)                                           \
554         do {                                                                   \
555           struct _align { char a; type b; };                                   \
556           unsigned off = offsetof(struct _align, b);                           \
557           if (off > align)                                                     \
558             align = off;                                                       \
559         } while (0)
560 
get_native_alignment(void)561 unsigned get_native_alignment(void)
562 {
563   unsigned align = 0;
564 
565   CHECK_NATIVE_ALIGNMENT(int);
566   CHECK_NATIVE_ALIGNMENT(int *);
567   CHECK_NATIVE_ALIGNMENT(long);
568   CHECK_NATIVE_ALIGNMENT(float);
569   CHECK_NATIVE_ALIGNMENT(double);
570 #if ARCH_HAVE_LONG_LONG
571   CHECK_NATIVE_ALIGNMENT(long long);
572 #endif
573 #if ARCH_HAVE_LONG_DOUBLE
574   CHECK_NATIVE_ALIGNMENT(long double);
575 #endif
576 
577   native_alignment = align;
578 
579   return align;
580 }
581 
582 #undef CHECK_NATIVE_ALIGNMENT
583 
584 /*******************************************************************************
585 *
586 *   ROUTINE: get_native_compound_alignment
587 *
588 *   WRITTEN BY: Marcus Holland-Moritz             ON: Aug 2004
589 *   CHANGED BY:                                   ON:
590 *
591 ********************************************************************************
592 *
593 * DESCRIPTION: Determine the native compound alignment and store it to the
594 *              global native_compound_alignment.
595 *
596 *   ARGUMENTS:
597 *
598 *     RETURNS:
599 *
600 *******************************************************************************/
601 
get_native_compound_alignment(void)602 unsigned get_native_compound_alignment(void)
603 {
604   struct _align {
605     char a;
606     struct {
607       char x;
608     }    b;
609   };
610 
611   unsigned align = offsetof(struct _align, b);
612 
613   native_compound_alignment = align;
614 
615   return align;
616 }
617 
618 /*******************************************************************************
619 *
620 *   ROUTINE: get_native_enum_size
621 *
622 *   WRITTEN BY: Marcus Holland-Moritz             ON: Aug 2004
623 *   CHANGED BY:                                   ON:
624 *
625 ********************************************************************************
626 *
627 * DESCRIPTION: Determine the native enum size.
628 *
629 *   ARGUMENTS:
630 *
631 *     RETURNS:
632 *
633 *******************************************************************************/
634 
get_native_enum_size(void)635 int get_native_enum_size(void)
636 {
637   enum pbyte { PB1 =      0, PB2 =   255 };
638   enum nbyte { NB1 =   -128, NB2 =   127 };
639   enum pword { PW1 =      0, PW2 = 65535 };
640   enum nword { NW1 = -32768, NW2 = 32767 };
641   enum plong { PL1 =      0, PL2 = 65536 };
642   enum nlong { NL1 = -32768, NL2 = 32768 };
643 
644   if (sizeof(enum pbyte) == 2 && sizeof(enum nbyte) == 1 &&
645       sizeof(enum pword) == 4 && sizeof(enum nword) == 2 &&
646       sizeof(enum plong) == 4 && sizeof(enum nlong) == 4)
647     return -1;
648 
649   if (sizeof(enum pbyte) == 1 && sizeof(enum nbyte) == 1 &&
650       sizeof(enum pword) == 2 && sizeof(enum nword) == 2 &&
651       sizeof(enum plong) == 4 && sizeof(enum nlong) == 4)
652     return 0;
653 
654   if (sizeof(enum pbyte) == sizeof(enum nbyte) &&
655       sizeof(enum pbyte) == sizeof(enum pword) &&
656       sizeof(enum pbyte) == sizeof(enum nword) &&
657       sizeof(enum pbyte) == sizeof(enum plong) &&
658       sizeof(enum pbyte) == sizeof(enum nlong))
659     return sizeof(enum pbyte);
660 
661   fatal_error("Unsupported native enum size (%d:%d:%d:%d:%d:%d)",
662               sizeof(enum pbyte), sizeof(enum nbyte), sizeof(enum pword),
663               sizeof(enum nword), sizeof(enum plong), sizeof(enum nlong));
664 
665   return -1000;
666 }
667 
668 /*******************************************************************************
669 *
670 *   ROUTINE: get_native_unsigned_chars
671 *
672 *   WRITTEN BY: Marcus Holland-Moritz             ON: Jan 2006
673 *   CHANGED BY:                                   ON:
674 *
675 ********************************************************************************
676 *
677 * DESCRIPTION: Determine if native chars are unsigned.
678 *
679 *   ARGUMENTS:
680 *
681 *     RETURNS:
682 *
683 *******************************************************************************/
684 
get_native_unsigned_chars(void)685 int get_native_unsigned_chars(void)
686 {
687   char c = -1;
688   int  i = (int) c;
689 
690   if (i == -1)
691     return 0;
692 
693   if (i > 0)
694     return 1;
695 
696   fatal_error("Strange result of cast from char to int (%d)", i);
697 
698   return -1000;
699 }
700 
701 /*******************************************************************************
702 *
703 *   ROUTINE: get_native_unsigned_bitfields
704 *
705 *   WRITTEN BY: Marcus Holland-Moritz             ON: Jan 2006
706 *   CHANGED BY:                                   ON:
707 *
708 ********************************************************************************
709 *
710 * DESCRIPTION: Determine if native bitfields are unsigned.
711 *
712 *   ARGUMENTS:
713 *
714 *     RETURNS:
715 *
716 *******************************************************************************/
717 
get_native_unsigned_bitfields(void)718 int get_native_unsigned_bitfields(void)
719 {
720   struct { int a:3; } x = { -1 };
721   int  i = (int) x.a;
722 
723   if (i == -1)
724     return 0;
725 
726   if (i > 0)
727     return 1;
728 
729   fatal_error("Strange result of cast from bitfield to int (%d)", i);
730 
731   return -1000;
732 }
733 
734