// Skip if not target: i?86-*-linux* i?86-*-freebsd* ia64*-*-* // Special g++ Options: -malign-double // Origin: Alex Samuel /* Test the layout of bitfields in C aggretagtes for compliance with the IA-64 ABI. */ #include template 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 ()) /* 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; }