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