summaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.old-deja/g++.abi/bitfields.C
blob: d5c3192095de4c77349fb44c5705f0a27d2b05c1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// { dg-do run { target i?86-*-linux* x86_64-*-linux* i?86-*-freebsd* } }
// { dg-require-effective-target ilp32 }
// { dg-options "-malign-double" }
// Origin: Alex Samuel <samuel@codesourcery.com>

/* Test the layout of bitfields in C aggretagtes for compliance with
   the IA-64 ABI.  */

#include <cstring>

template<typename T>
inline unsigned
alignmentof ()
{
  struct S
  {
    char start_;
    T object_;
  };

  return (unsigned) & ((S *) 0)->object_;
}

/* Computes the alignment, in bytes, of TYPE.  */

#define alignof(type) (alignmentof<type> ())

/* Returns true iff all the bits in the range 
   START_BIT <= bit < START_BIT + NUM_BITS, and only those bits, are
   set in the region of memory starting at BUF of LENGTH bytes.  */

bool
check_bits (char *buf,
	    unsigned length,
	    unsigned start_bit,
	    unsigned num_bits)
{
  for (unsigned bit = 0; bit < 8 * length; ++bit) {
    bool is_set = (buf[bit / 8] & (1 << (bit % 8))) != 0;
    if (start_bit <= bit && bit < start_bit + num_bits) {
      if (! is_set)
	return false;
    }
    else {
      if (is_set)
	return false;
    }
  }
  return true;
}

/* Creates a variable of type AGGREGATE, sets FIELD to -1, and
   verifies that NUM_BITS bits starting at START_BIT, and no other
   bits, are set.  If the check fails, returns with value RVAL.  */

#define CHECK_FIELD(AGGREGATE, FIELD, START_BIT, NUM_BITS, RVAL)          \
  do {                                                                    \
    AGGREGATE a__;                                                        \
    std::memset (& a__, 0, sizeof (a__));                                 \
    a__.FIELD = -1;                                                       \
    if (! check_bits ((char *) & a__, sizeof (a__), START_BIT, NUM_BITS)) \
      return RVAL;                                                        \
  } while (0);



/* Structs S1, S2, S3, S4, and union U5 are taken from Intel, "IA-64
   Software Conventions and Runtime Architecture Guide", version of
   August 1999.  */

struct S1
{
  int       j : 5;
  int       k : 6;
  int       m : 7;
};

#ifdef HAVE_IA64_TYPES
struct S2
{
  short     s : 9;
  __int64   j : 9;
  char      c    ;
  short     t : 9;
  short     u : 9;
  char      d    ;
};
#endif  /* HAVE_IA64_TYPES  */

struct S3
{
  char      c    ;
  short     s : 8;
};

union U4
{
  char      c    ;
  short     s : 8;
};

struct S5
{
  char      c    ;
  int         : 0;
  char      d    ;
  short       : 9;
  char      e    ;
  char        : 0;
};


int
main ()
{
  if (sizeof (struct S1)		!=  4)
    return 1;
  if (alignof (struct S1)		!=  4)
    return 2;
  CHECK_FIELD (S1, j,  0,  5,  3);
  CHECK_FIELD (S1, k,  5,  6,  4);
  CHECK_FIELD (S1, m, 11,  7,  5);

#ifdef HAVE_IA64_TYPES
  if (sizeof (struct S2)		!= 16)
    return 6;
  if (alignof (struct S2)		!=  8)
    return 7;
  CHECK_FIELD (S2, s,  0,  9,  8);
  CHECK_FIELD (S2, j,  9,  9,  9);
  CHECK_FIELD (S2, c, 24,  8, 10);
  CHECK_FIELD (S2, t, 32,  9, 11);
  CHECK_FIELD (S2, u, 48,  9, 12);
  CHECK_FIELD (S2, d, 64,  8, 13);
#endif  /* HAVE_IA64_TYPES  */

  if (sizeof (struct S3)		!=  2)
    return 14;
  if (sizeof (struct S3)		!=  2)
    return 15;
  CHECK_FIELD (S3, c,  0,  8, 16);
  CHECK_FIELD (S3, s,  8,  8, 17);

  if (sizeof (union U4) 		!=  2)
    return 18;
  if (alignof (union U4)		!=  2)
    return 19;
  CHECK_FIELD (U4, c,  0,  8, 20);
  CHECK_FIELD (U4, s,  0,  8, 21);

  if (sizeof (struct S5)		!=  9)
    return 22;
  if (alignof (struct S5)		!=  1)
    return 23;
  CHECK_FIELD (S5, c,  0,  8, 24);
  CHECK_FIELD (S5, d, 32,  8, 25);
  CHECK_FIELD (S5, e, 64,  8, 26);

  return 0;
}