1 // { dg-do run { target i?86-*-linux* i?86-*-gnu* x86_64-*-linux* i?86-*-freebsd* } }
2 // { dg-require-effective-target ilp32 }
3 // { dg-options "-malign-double" }
4 // Origin: Alex Samuel <samuel@codesourcery.com>
5 
6 /* Test the layout of bitfields in C aggretagtes for compliance with
7    the IA-64 ABI.  */
8 
9 #include <cstring>
10 
11 template<typename T>
12 inline unsigned
alignmentof()13 alignmentof ()
14 {
15   struct S
16   {
17     char start_;
18     T object_;
19   };
20 
21   return (unsigned) & ((S *) 0)->object_;
22 }
23 
24 /* Computes the alignment, in bytes, of TYPE.  */
25 
26 #define alignof(type) (alignmentof<type> ())
27 
28 /* Returns true iff all the bits in the range
29    START_BIT <= bit < START_BIT + NUM_BITS, and only those bits, are
30    set in the region of memory starting at BUF of LENGTH bytes.  */
31 
32 bool
check_bits(char * buf,unsigned length,unsigned start_bit,unsigned num_bits)33 check_bits (char *buf,
34 	    unsigned length,
35 	    unsigned start_bit,
36 	    unsigned num_bits)
37 {
38   for (unsigned bit = 0; bit < 8 * length; ++bit) {
39     bool is_set = (buf[bit / 8] & (1 << (bit % 8))) != 0;
40     if (start_bit <= bit && bit < start_bit + num_bits) {
41       if (! is_set)
42 	return false;
43     }
44     else {
45       if (is_set)
46 	return false;
47     }
48   }
49   return true;
50 }
51 
52 /* Creates a variable of type AGGREGATE, sets FIELD to -1, and
53    verifies that NUM_BITS bits starting at START_BIT, and no other
54    bits, are set.  If the check fails, returns with value RVAL.  */
55 
56 #define CHECK_FIELD(AGGREGATE, FIELD, START_BIT, NUM_BITS, RVAL)          \
57   do {                                                                    \
58     AGGREGATE a__;                                                        \
59     std::memset (& a__, 0, sizeof (a__));                                 \
60     a__.FIELD = -1;                                                       \
61     if (! check_bits ((char *) & a__, sizeof (a__), START_BIT, NUM_BITS)) \
62       return RVAL;                                                        \
63   } while (0);
64 
65 
66 
67 /* Structs S1, S2, S3, S4, and union U5 are taken from Intel, "IA-64
68    Software Conventions and Runtime Architecture Guide", version of
69    August 1999.  */
70 
71 struct S1
72 {
73   int       j : 5;
74   int       k : 6;
75   int       m : 7;
76 };
77 
78 #ifdef HAVE_IA64_TYPES
79 struct S2
80 {
81   short     s : 9;
82   __int64   j : 9;
83   char      c    ;
84   short     t : 9;
85   short     u : 9;
86   char      d    ;
87 };
88 #endif  /* HAVE_IA64_TYPES  */
89 
90 struct S3
91 {
92   char      c    ;
93   short     s : 8;
94 };
95 
96 union U4
97 {
98   char      c    ;
99   short     s : 8;
100 };
101 
102 struct S5
103 {
104   char      c    ;
105   int         : 0;
106   char      d    ;
107   short       : 9;
108   char      e    ;
109   char        : 0;
110 };
111 
112 
113 int
main()114 main ()
115 {
116   if (sizeof (struct S1)		!=  4)
117     return 1;
118   if (alignof (struct S1)		!=  4)
119     return 2;
120   CHECK_FIELD (S1, j,  0,  5,  3);
121   CHECK_FIELD (S1, k,  5,  6,  4);
122   CHECK_FIELD (S1, m, 11,  7,  5);
123 
124 #ifdef HAVE_IA64_TYPES
125   if (sizeof (struct S2)		!= 16)
126     return 6;
127   if (alignof (struct S2)		!=  8)
128     return 7;
129   CHECK_FIELD (S2, s,  0,  9,  8);
130   CHECK_FIELD (S2, j,  9,  9,  9);
131   CHECK_FIELD (S2, c, 24,  8, 10);
132   CHECK_FIELD (S2, t, 32,  9, 11);
133   CHECK_FIELD (S2, u, 48,  9, 12);
134   CHECK_FIELD (S2, d, 64,  8, 13);
135 #endif  /* HAVE_IA64_TYPES  */
136 
137   if (sizeof (struct S3)		!=  2)
138     return 14;
139   if (sizeof (struct S3)		!=  2)
140     return 15;
141   CHECK_FIELD (S3, c,  0,  8, 16);
142   CHECK_FIELD (S3, s,  8,  8, 17);
143 
144   if (sizeof (union U4) 		!=  2)
145     return 18;
146   if (alignof (union U4)		!=  2)
147     return 19;
148   CHECK_FIELD (U4, c,  0,  8, 20);
149   CHECK_FIELD (U4, s,  0,  8, 21);
150 
151   if (sizeof (struct S5)		!=  9)
152     return 22;
153   if (alignof (struct S5)		!=  1)
154     return 23;
155   CHECK_FIELD (S5, c,  0,  8, 24);
156   CHECK_FIELD (S5, d, 32,  8, 25);
157   CHECK_FIELD (S5, e, 64,  8, 26);
158 
159   return 0;
160 }
161