333-struct-assign-big.c (2343B)
1 /* Struct/union assignment must memcpy the whole aggregate, not just 2 * the first 8 bytes. cg-assign's scalar path emitted one 8-byte 3 * load + store, dropping every field at offset >= 8 — which silently 4 * broke vswap() in tcc.flat.c (SValue is 64 bytes), surfacing as the 5 * vtop[-1].r < VT_CONST assertion in arm64-gen.c during tcc-cc. 6 * 7 * Exercises: 8 * - direct struct lvalue = lvalue assignment 9 * - assignment through pointer indices (vtop[0] = vtop[-1] shape) 10 * - tmp = src; src = dst; dst = tmp three-way swap 11 * - fields at offsets 0, 4, 8, 16+ — including a sub-word field 12 * past offset 8 (mirrors SValue.r at offset 16) 13 */ 14 15 struct Big { 16 int a; 17 int b; 18 unsigned short r; 19 unsigned short r2; 20 long c[2]; 21 void *sym; 22 }; 23 24 static struct Big buf[4]; 25 26 static void swap2(struct Big *p) { 27 struct Big tmp; 28 tmp = p[0]; 29 p[0] = p[-1]; 30 p[-1] = tmp; 31 } 32 33 int main(int argc, char **argv) { 34 /* Direct assignment between two named struct lvalues. */ 35 struct Big x; 36 struct Big y; 37 x.a = 0xA1; x.b = 0xA2; x.r = 0xA3; x.r2 = 0xA4; 38 x.c[0] = 0xA5; x.c[1] = 0xA6; x.sym = (void *)0xA7; 39 y = x; 40 if (y.a != 0xA1) return 1; 41 if (y.b != 0xA2) return 2; 42 if (y.r != 0xA3) return 3; 43 if (y.r2 != 0xA4) return 4; 44 if (y.c[0] != 0xA5) return 5; 45 if (y.c[1] != 0xA6) return 6; 46 if (y.sym != (void *)0xA7) return 7; 47 48 /* Pointer-indexed struct swap (tcc's vswap pattern). */ 49 buf[0].a = 0x01; buf[0].b = 0x02; buf[0].r = 0x03; buf[0].r2 = 0x04; 50 buf[0].c[0] = 0x05; buf[0].c[1] = 0x06; buf[0].sym = (void *)0x07; 51 buf[1].a = 0x11; buf[1].b = 0x12; buf[1].r = 0x13; buf[1].r2 = 0x14; 52 buf[1].c[0] = 0x15; buf[1].c[1] = 0x16; buf[1].sym = (void *)0x17; 53 swap2(&buf[1]); 54 if (buf[0].a != 0x11) return 11; 55 if (buf[0].b != 0x12) return 12; 56 if (buf[0].r != 0x13) return 13; 57 if (buf[0].r2 != 0x14) return 14; 58 if (buf[0].c[0] != 0x15) return 15; 59 if (buf[0].c[1] != 0x16) return 16; 60 if (buf[0].sym != (void *)0x17) return 17; 61 if (buf[1].a != 0x01) return 21; 62 if (buf[1].b != 0x02) return 22; 63 if (buf[1].r != 0x03) return 23; 64 if (buf[1].r2 != 0x04) return 24; 65 if (buf[1].c[0] != 0x05) return 25; 66 if (buf[1].c[1] != 0x06) return 26; 67 if (buf[1].sym != (void *)0x07) return 27; 68 69 return 0; 70 }