1// { dg-do run { target i?86-*-linux* 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
11template<typename T>
12inline unsigned
13alignmentof ()
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
32bool
33check_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
71struct S1
72{
73  int       j : 5;
74  int       k : 6;
75  int       m : 7;
76};
77
78#ifdef HAVE_IA64_TYPES
79struct 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
90struct S3
91{
92  char      c    ;
93  short     s : 8;
94};
95
96union U4
97{
98  char      c    ;
99  short     s : 8;
100};
101
102struct S5
103{
104  char      c    ;
105  int         : 0;
106  char      d    ;
107  short       : 9;
108  char      e    ;
109  char        : 0;
110};
111
112
113int
114main ()
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