cgen: route aggregate field-to-field assignment through the aggregate copier
The direct-field assignment arms enumerate CALL, STRUCTLIT, and local IDENT producers; an addressable N_DOT/N_INDEX/deref rhs fell through to the scalar tail, so a 16-byte struct field copied only its first word. Resolve both places through the existing address funnels and use the tail-aware aggregate copier. Both stages.
This commit is contained in:
73
test/lang/aggregate_field_copy_test.ww
Normal file
73
test/lang/aggregate_field_copy_test.ww
Normal file
@@ -0,0 +1,73 @@
|
||||
// Addressable aggregate fields must copy every byte. A scalar fallback used
|
||||
// to copy only the first word of a 16-byte nested value under both stages.
|
||||
|
||||
package aggregate_field_copy_test;
|
||||
|
||||
type pair = struct {
|
||||
first: i64,
|
||||
second: i64,
|
||||
};
|
||||
|
||||
type outer = struct {
|
||||
guard: i64,
|
||||
value: pair,
|
||||
tail: i64,
|
||||
};
|
||||
|
||||
type nested = struct {
|
||||
outer: outer,
|
||||
};
|
||||
|
||||
let globalsource: outer;
|
||||
let globaltarget: outer;
|
||||
|
||||
fn check(v: *outer, first: i64, second: i64) void = {
|
||||
assert(v.value.first == first);
|
||||
assert(v.value.second == second);
|
||||
assert(v.guard == 91);
|
||||
assert(v.tail == 92);
|
||||
};
|
||||
|
||||
@test fn aggregate_field_memory_copy() void = {
|
||||
let source: outer;
|
||||
source.value.first = 11;
|
||||
source.value.second = 12;
|
||||
let target: outer;
|
||||
target.guard = 91;
|
||||
target.value.first = 1;
|
||||
target.value.second = 2;
|
||||
target.tail = 92;
|
||||
target.value = source.value;
|
||||
check(&target, 11, 12);
|
||||
|
||||
let pointer: *outer = ⌖
|
||||
source.value.first = 21;
|
||||
source.value.second = 22;
|
||||
pointer.value = source.value;
|
||||
check(&target, 21, 22);
|
||||
|
||||
let deep: nested;
|
||||
deep.outer.value.first = 31;
|
||||
deep.outer.value.second = 32;
|
||||
target.value = deep.outer.value;
|
||||
check(&target, 31, 32);
|
||||
|
||||
let indexed: [2]pair = [pair{first=5,second=6},
|
||||
pair{first=35,second=36}];
|
||||
target.value = indexed[1];
|
||||
check(&target, 35, 36);
|
||||
|
||||
let pointed: pair = pair{first=37,second=38};
|
||||
let sourcepointer: *pair = &pointed;
|
||||
target.value = *sourcepointer;
|
||||
check(&target, 37, 38);
|
||||
|
||||
globalsource.value.first = 41;
|
||||
globalsource.value.second = 42;
|
||||
globaltarget.guard = 91;
|
||||
globaltarget.value.first = 3;
|
||||
globaltarget.value.second = 4;
|
||||
globaltarget.tail = 92;
|
||||
globaltarget.value = globalsource.value;
|
||||
check(&globaltarget, 41, 42);
|
||||
};
|
||||
Reference in New Issue
Block a user