1 1.6 rillig /* $NetBSD: gcc_attribute_aligned.c,v 1.6 2023/07/07 19:45:22 rillig Exp $ */ 2 1.1 rillig # 3 "gcc_attribute_aligned.c" 3 1.1 rillig 4 1.1 rillig /* 5 1.1 rillig * Test size computations on aligned and packed structs. 6 1.1 rillig */ 7 1.1 rillig 8 1.6 rillig /* lint1-extra-flags: -X 351 */ 9 1.6 rillig 10 1.1 rillig typedef unsigned short uint16_t; 11 1.1 rillig typedef unsigned int uint32_t; 12 1.1 rillig typedef unsigned long long uint64_t; 13 1.1 rillig 14 1.1 rillig /* from sys/arch/x86/include/cpu_extended_state.h */ 15 1.1 rillig 16 1.1 rillig union fp_addr { 17 1.1 rillig uint64_t fa_64; 18 1.1 rillig struct { 19 1.1 rillig uint32_t fa_off; 20 1.1 rillig uint16_t fa_seg; 21 1.1 rillig uint16_t fa_opcode; 22 1.1 rillig } fa_32; 23 1.1 rillig } __attribute__((packed)) __attribute__((aligned(4))); 24 1.1 rillig 25 1.5 rillig /* Each variant of the union has size 8. */ 26 1.5 rillig /* expect+1: error: negative array dimension (-8) [20] */ 27 1.5 rillig typedef int sizeof_fp_addr[-(int)sizeof(union fp_addr)]; 28 1.5 rillig 29 1.1 rillig struct fpacc87 { 30 1.1 rillig uint64_t f87_mantissa; 31 1.1 rillig uint16_t f87_exp_sign; 32 1.1 rillig } __attribute__((packed)) __attribute__((aligned(2))); 33 1.1 rillig 34 1.5 rillig /* 35 1.5 rillig * Due to the 'packed', the uint64_t does not need to be aligned on an 8-byte 36 1.5 rillig * boundary, which allows the struct to have the minimal required size of 10. 37 1.5 rillig */ 38 1.5 rillig /* expect+1: error: negative array dimension (-10) [20] */ 39 1.5 rillig typedef int sizeof_fpacc87[-(int)sizeof(struct fpacc87)]; 40 1.5 rillig 41 1.1 rillig struct save87 { 42 1.1 rillig uint16_t s87_cw __attribute__((aligned(4))); 43 1.1 rillig uint16_t s87_sw __attribute__((aligned(4))); 44 1.1 rillig uint16_t s87_tw __attribute__((aligned(4))); 45 1.1 rillig union fp_addr s87_ip; 46 1.1 rillig union fp_addr s87_dp; 47 1.1 rillig struct fpacc87 s87_ac[8]; 48 1.1 rillig }; 49 1.1 rillig 50 1.5 rillig /* FIXME: @4 2 + @4 2 + @4 2 + @4 8 + @4 8 + @2 (8 * 10) == 108 */ 51 1.5 rillig /* expect+1: error: negative array dimension (-104) [20] */ 52 1.5 rillig typedef int sizeof_save87[-(int)sizeof(struct save87)]; 53 1.4 rillig 54 1.4 rillig 55 1.4 rillig void 56 1.4 rillig aligned_struct_member(void) 57 1.4 rillig { 58 1.4 rillig struct aligned { 59 1.4 rillig int first; 60 1.4 rillig int second __attribute__((__aligned__(16))); 61 1.4 rillig }; 62 1.4 rillig 63 1.5 rillig /* 64 1.5 rillig * Aligning 'second' to a 16-bytes boundary not only aligns the member 65 1.5 rillig * inside the structure, it also affects the alignment requirement of 66 1.5 rillig * the whole structure. Due to this struct alignment, the size of the 67 1.5 rillig * structure gets rounded up to 32 instead of using the minimally 68 1.5 rillig * necessary storage of 20. 69 1.5 rillig * 70 1.5 rillig * https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html 71 1.5 rillig */ 72 1.5 rillig /* TODO: should be -32 instead of -8. */ 73 1.4 rillig /* expect+1: error: negative array dimension (-8) [20] */ 74 1.4 rillig typedef int ctassert[-(int)sizeof(struct aligned)]; 75 1.4 rillig } 76