This commit is contained in:
David Rubin 2025-11-25 13:29:47 +01:00 committed by GitHub
commit 9a06193033
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 73 additions and 39 deletions

View file

@ -14640,8 +14640,9 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const mutable_alloc = try block.addTy(.alloc, alloc_ty);
// if both the source and destination are arrays
// we can hotpath via a memcpy.
// there's nothing to copy
if (result_len == 0 and res_sent_val == null) return mutable_alloc;
if (lhs_ty.zigTypeTag(zcu) == .pointer and
rhs_ty.zigTypeTag(zcu) == .pointer)
{
@ -14654,48 +14655,75 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
});
const many_ty = slice_ty.slicePtrFieldType(zcu);
const many_alloc = try block.addBitCast(many_ty, mutable_alloc);
const many_ty_ref = Air.internedToRef(many_ty.toIntern());
// lhs_dest_slice = dest[0..lhs.len]
const slice_ty_ref = Air.internedToRef(slice_ty.toIntern());
const lhs_len_ref = try pt.intRef(.usize, lhs_len);
const lhs_dest_slice = try block.addInst(.{
.tag = .slice,
.data = .{ .ty_pl = .{
.ty = slice_ty_ref,
.payload = try sema.addExtra(Air.Bin{
.lhs = many_alloc,
.rhs = lhs_len_ref,
}),
} },
});
_ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs);
// @memcpy(@as(*[lhs.len]T, dst[0..lhs.len]), lhs.ptr)
if (lhs_len != 0) {
// [lhs.len]T
const array_ty = try pt.arrayType(.{
.child = resolved_elem_ty.toIntern(),
.len = lhs_len,
});
// *[lhs.len]T
const mutable_ty = try pt.ptrTypeSema(.{
.child = array_ty.toIntern(),
.flags = .{ .address_space = ptr_as },
});
const lhs_dest_slice = try block.addBitCast(mutable_ty, mutable_alloc);
// rhs_dest_slice = dest[lhs.len..][0..rhs.len]
const rhs_len_ref = try pt.intRef(.usize, rhs_len);
const rhs_dest_offset = try block.addInst(.{
.tag = .ptr_add,
.data = .{ .ty_pl = .{
.ty = Air.internedToRef(many_ty.toIntern()),
.payload = try sema.addExtra(Air.Bin{
.lhs = many_alloc,
.rhs = lhs_len_ref,
}),
} },
});
const rhs_dest_slice = try block.addInst(.{
.tag = .slice,
.data = .{ .ty_pl = .{
.ty = slice_ty_ref,
.payload = try sema.addExtra(Air.Bin{
.lhs = rhs_dest_offset,
.rhs = rhs_len_ref,
}),
} },
});
const lhs_src_pointer = if (lhs_ty.isSlice(zcu))
try block.addInst(.{
.tag = .slice_ptr,
.data = .{ .ty_op = .{
.ty = many_ty_ref,
.operand = lhs,
} },
})
else
lhs;
_ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs_src_pointer);
}
_ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs);
if (rhs_len != 0) {
const many_alloc = try block.addBitCast(many_ty, mutable_alloc);
const rhs_dest_offset = try block.addInst(.{
.tag = .ptr_add,
.data = .{ .ty_pl = .{
.ty = many_ty_ref,
.payload = try sema.addExtra(Air.Bin{
.lhs = many_alloc,
.rhs = lhs_len_ref,
}),
} },
});
// [rhs.len]T
const array_ty = try pt.arrayType(.{
.child = resolved_elem_ty.toIntern(),
.len = rhs_len,
});
// *[rhs.len]T
const mutable_ty = try pt.ptrTypeSema(.{
.child = array_ty.toIntern(),
.flags = .{ .address_space = ptr_as },
});
const rhs_dest_slice = try block.addBitCast(mutable_ty, rhs_dest_offset);
const rhs_src_pointer = if (rhs_ty.isSlice(zcu))
try block.addInst(.{
.tag = .slice_ptr,
.data = .{ .ty_op = .{
.ty = many_ty_ref,
.operand = rhs,
} },
})
else
rhs;
_ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs_src_pointer);
}
if (res_sent_val) |sent_val| {
const elem_index = try pt.intRef(.usize, result_len);

View file

@ -92,6 +92,12 @@ test "array init with concat" {
try expect(std.mem.eql(u8, &i, "abcd"));
}
test "array concat zero length pointers" {
var x: *const [0]u8 = &.{};
_ = &x;
_ = @as([]const u8, "") ++ x;
}
test "array init with mult" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO