stage2: fix Value.copy not copying arrays

This commit is contained in:
Andrew Kelley
2021-10-21 20:28:32 -07:00
parent 7f70c27e9d
commit 1bce0ed046
2 changed files with 21 additions and 14 deletions

View File

@@ -6912,11 +6912,11 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const final_len = lhs_info.len + rhs_info.len;
const final_len_including_sent = final_len + @boolToInt(res_sent != null);
const is_pointer = lhs_ty.zigTypeTag() == .Pointer;
const lhs_sub_val = if (is_pointer) (try lhs_val.pointerDeref(sema.arena)).? else lhs_val;
const rhs_sub_val = if (is_pointer) (try rhs_val.pointerDeref(sema.arena)).? else rhs_val;
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const lhs_sub_val = if (is_pointer) (try lhs_val.pointerDeref(anon_decl.arena())).? else lhs_val;
const rhs_sub_val = if (is_pointer) (try rhs_val.pointerDeref(anon_decl.arena())).? else rhs_val;
const buf = try anon_decl.arena().alloc(Value, final_len_including_sent);
{
var i: u64 = 0;
@@ -6936,18 +6936,20 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
buf[final_len] = try rs.copy(anon_decl.arena());
break :ty try Type.Tag.array_sentinel.create(anon_decl.arena(), .{
.len = final_len,
.elem_type = lhs_info.elem_type,
.sentinel = rs,
.elem_type = try lhs_info.elem_type.copy(anon_decl.arena()),
.sentinel = try rs.copy(anon_decl.arena()),
});
} else try Type.Tag.array.create(anon_decl.arena(), .{
.len = final_len,
.elem_type = lhs_info.elem_type,
.elem_type = try lhs_info.elem_type.copy(anon_decl.arena()),
});
const val = try Value.Tag.array.create(anon_decl.arena(), buf);
return if (is_pointer)
sema.analyzeDeclRef(try anon_decl.finish(ty, val))
else
sema.analyzeDeclVal(block, .unneeded, try anon_decl.finish(ty, val));
const decl = try anon_decl.finish(ty, val);
if (is_pointer) {
return sema.analyzeDeclRef(decl);
} else {
return sema.analyzeDeclVal(block, .unneeded, decl);
}
} else {
return sema.fail(block, lhs_src, "TODO runtime array_cat", .{});
}
@@ -6990,10 +6992,11 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const final_len_including_sent = final_len + @boolToInt(mulinfo.sentinel != null);
if (try sema.resolveDefinedValue(block, lhs_src, lhs)) |lhs_val| {
const lhs_sub_val = if (lhs_ty.zigTypeTag() == .Pointer) (try lhs_val.pointerDeref(sema.arena)).? else lhs_val;
var anon_decl = try block.startAnonDecl();
defer anon_decl.deinit();
const lhs_sub_val = if (lhs_ty.zigTypeTag() == .Pointer) (try lhs_val.pointerDeref(anon_decl.arena())).? else lhs_val;
const final_ty = if (mulinfo.sentinel) |sent|
try Type.Tag.array_sentinel.create(anon_decl.arena(), .{
.len = final_len,
@@ -7010,7 +7013,8 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
// Optimization for the common pattern of a single element repeated N times, such
// as zero-filling a byte array.
const val = if (mulinfo.len == 1) blk: {
const copied_val = try (try lhs_sub_val.elemValue(sema.arena, 0)).copy(anon_decl.arena());
const elem_val = try lhs_sub_val.elemValue(sema.arena, 0);
const copied_val = try elem_val.copy(anon_decl.arena());
break :blk try Value.Tag.repeated.create(anon_decl.arena(), copied_val);
} else blk: {
// the actual loop
@@ -7027,10 +7031,11 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
}
break :blk try Value.Tag.array.create(anon_decl.arena(), buf);
};
const decl = try anon_decl.finish(final_ty, val);
if (lhs_ty.zigTypeTag() == .Pointer) {
return sema.analyzeDeclRef(try anon_decl.finish(final_ty, val));
return sema.analyzeDeclRef(decl);
} else {
return sema.analyzeDeclVal(block, .unneeded, try anon_decl.finish(final_ty, val));
return sema.analyzeDeclVal(block, .unneeded, decl);
}
}
return sema.fail(block, lhs_src, "TODO runtime array_mul", .{});

View File

@@ -514,7 +514,9 @@ pub const Value = extern union {
.base = payload.base,
.data = try arena.alloc(Value, payload.data.len),
};
std.mem.copy(Value, new_payload.data, payload.data);
for (new_payload.data) |*elem, i| {
elem.* = try payload.data[i].copy(arena);
}
return Value{ .ptr_otherwise = &new_payload.base };
},
.slice => {