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