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