parse,check,type,wwi: @packed struct attribute, both stages (#51)
Hare/harec @packed struct layout: no inter-field or trailing padding, align =
max field align (NOT forced to 1) — matches harec type_store.c + types.c:621
(packed{u8,u64}=size 9/align 8). Parser consumes inline @packed (loud-rejects
unknown struct attrs, both stages); layout gates padding on !packed; cstage
type_eq enforces packed type-distinctness; the .wwi producer round-trips
"struct @packed {". wwstage sets slotsize=size for packed so its composite-ABI
copy matches cstage byte-for-byte. cstage identity is faithful; wwstage identity
rides the deferred #224 nominal-resolvealias arc (#108). Both stages byte-id;
447 tests pass.
This commit is contained in:
@@ -1311,11 +1311,17 @@ fn astsize(c: *checker, t: *syntax.node) i64 = {
|
||||
if (f.kind == syntax.nkind.N_TFIELD) {
|
||||
let fa: i64 = astalign(c, f.lhs);
|
||||
if (fa > maxal) { maxal = fa; };
|
||||
off = (off + fa - 1i64) & ~(fa - 1i64);
|
||||
// packed: no inter-field padding (harec
|
||||
// type_store.c:206-213); align value unchanged.
|
||||
if (t.packed == 0) {
|
||||
off = (off + fa - 1i64) & ~(fa - 1i64);
|
||||
};
|
||||
off += astsize(c, f.lhs);
|
||||
};
|
||||
f = f.next;
|
||||
};
|
||||
// packed: skip trailing pad-to-align (harec type_store.c:886).
|
||||
if (t.packed != 0) { return off; };
|
||||
return (off + maxal - 1i64) & ~(maxal - 1i64);
|
||||
};
|
||||
if (k == syntax.nkind.N_TTAGGED) {
|
||||
@@ -1528,7 +1534,10 @@ fn astoffset(c: *checker, dot: *syntax.node) i64 = {
|
||||
for (f != nil) {
|
||||
if (f.kind == syntax.nkind.N_TFIELD) {
|
||||
let fa: i64 = astalign(c, f.lhs);
|
||||
off = (off + fa - 1i64) & ~(fa - 1i64);
|
||||
// packed: no inter-field padding (harec type_store.c:206-213).
|
||||
if (rtyp.packed == 0) {
|
||||
off = (off + fa - 1i64) & ~(fa - 1i64);
|
||||
};
|
||||
if (syntax.streq(f.str, dot.str)) { return off; };
|
||||
off += astsize(c, f.lhs);
|
||||
};
|
||||
@@ -2279,7 +2288,10 @@ fn tinfofornode(c: *checker, n: *syntax.node) *syntax.tinfo = {
|
||||
if (circularnamed(c, ft, f)) { ft = c.tc.tyerr; };
|
||||
if (ft != nil) {
|
||||
if (ft.align > maxalign) { maxalign = ft.align; };
|
||||
if (ft.align > 0u64) {
|
||||
// packed: no inter-field padding (harec
|
||||
// type_store.c:206-213); align still tracks the
|
||||
// max field align below.
|
||||
if (n.packed == 0 && ft.align > 0u64) {
|
||||
off = (off + ft.align - 1u64) & ~(ft.align - 1u64);
|
||||
};
|
||||
let fldoff: u64 = off;
|
||||
@@ -2303,14 +2315,29 @@ fn tinfofornode(c: *checker, n: *syntax.node) *syntax.tinfo = {
|
||||
f = f.next;
|
||||
};
|
||||
r.fields = fh;
|
||||
if (maxalign > 0u64) {
|
||||
r.size = (off + maxalign - 1u64) & ~(maxalign - 1u64);
|
||||
r.packed = n.packed;
|
||||
// packed: skip the trailing pad-to-align (harec
|
||||
// type_store.c:886 `!packed`); align value unchanged.
|
||||
if (n.packed != 0) {
|
||||
r.size = off;
|
||||
} else {
|
||||
if (maxalign > 0u64) {
|
||||
r.size = (off + maxalign - 1u64) & ~(maxalign - 1u64);
|
||||
};
|
||||
};
|
||||
r.align = maxalign;
|
||||
if ((soff & 7u64) != 0u64) {
|
||||
soff = (soff + 7u64) & ~7u64;
|
||||
// packed: slotsize == size — cstage has no slotsize, it uses the
|
||||
// (packed) size everywhere incl struct-ABI copy (cmd/w6c/cgen.c:
|
||||
// 15020). Aligning slotsize DOWN to size keeps every wwstage
|
||||
// slot-padded consumer byte-identical to cstage (rule 10).
|
||||
if (n.packed != 0) {
|
||||
r.slotsize = r.size;
|
||||
} else {
|
||||
if ((soff & 7u64) != 0u64) {
|
||||
soff = (soff + 7u64) & ~7u64;
|
||||
};
|
||||
r.slotsize = soff;
|
||||
};
|
||||
r.slotsize = soff;
|
||||
case syntax.nkind.N_TTAGGED:
|
||||
// THE tagged-union normalization SSoT (astsize/astalign delegate
|
||||
// here). Mirrors cstage resolve_type N_TTAGGED (cmd/wcc/check.c:
|
||||
|
||||
@@ -361,7 +361,13 @@ fn wwitype(fd: i32, t: *syntax.node) void = {
|
||||
wputs(fd, ") ");
|
||||
wwitype(fd, t.lhs);
|
||||
} else { if (t.kind == syntax.nkind.N_TSTRUCT) {
|
||||
wputs(fd, "struct { ");
|
||||
// re-emit `@packed` so the flag round-trips through
|
||||
// sep-compile (harec unparse/type.ha:122-126).
|
||||
if (t.packed != 0) {
|
||||
wputs(fd, "struct @packed { ");
|
||||
} else {
|
||||
wputs(fd, "struct { ");
|
||||
};
|
||||
let f: *syntax.node = t.list;
|
||||
for (f != nil) {
|
||||
if (f != t.list) { wputs(fd, ", "); };
|
||||
|
||||
Reference in New Issue
Block a user