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.
74 lines
1.6 KiB
Plaintext
74 lines
1.6 KiB
Plaintext
// 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);
|
|
};
|