kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

aggregate_copy_far_slot_misaligned.c (1894B)


      1 /* Aggregate copy of a 4-aligned record living in a far (>256B) frame slot.
      2  *
      3  * A struct returned by value is homed into a local that the large `pad` frame
      4  * pushes past the aarch64 stur/ldur +-256 range. The struct is 12 bytes with
      5  * 4-byte alignment, so its slot can land at a frame offset that is 4 (mod 8).
      6  * The store-into-local copy chunks the record as an 8-byte + a 4-byte access;
      7  * the 8-byte chunk is then at a 4-mod-8 offset, which a scaled ldr/str cannot
      8  * encode. The aarch64 far-slot fast path must detect the under-aligned access
      9  * and fall back to the address-build form instead of emitting an unencodable
     10  * scaled offset (which previously tripped a "far slot offset ... misaligned"
     11  * codegen panic). The `perturb` array nudges the frame layout so `a` lands on
     12  * the misaligned offset with the current allocator.
     13  *
     14  * x64/rv64 have no scaled-offset alignment constraint, so this just confirms
     15  * the aggregate copy stays correct everywhere. */
     16 
     17 struct loc {
     18   unsigned file, line, col;
     19 }; /* 12 bytes, align 4 */
     20 
     21 __attribute__((noinline)) static struct loc make_loc(unsigned x) {
     22   struct loc r;
     23   r.file = x;
     24   r.line = x + 1u;
     25   r.col = x + 2u;
     26   return r;
     27 }
     28 
     29 __attribute__((noinline)) static unsigned work(unsigned seed) {
     30   volatile long pad[40]; /* large frame: 'a' lands far from fp */
     31   volatile unsigned perturb[3];
     32   unsigned pt = 0;
     33   for (int i = 0; i < 40; i++) pad[i] = i;
     34   for (int i = 0; i < 3; i++) perturb[i] = seed + (unsigned)i;
     35   struct loc a = make_loc(seed); /* struct-return -> 8+4 stack copy */
     36   for (int i = 0; i < 3; i++) pt += perturb[i];
     37   /* Keep pad live without folding its (large) sum into the checksum. */
     38   for (int i = 0; i < 40; i++)
     39     if (pad[i] < 0) pt += (unsigned)pad[i];
     40   return a.file + a.line + a.col + pt;
     41 }
     42 
     43 int test_main(void) {
     44   /* a = {5,6,7} = 18 ; perturb = 5+6+7 = 18 ; total 36 */
     45   return (int)work(5u);
     46 }