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); const mutable_alloc = try block.addTy(.alloc, alloc_ty);
// if both the source and destination are arrays // there's nothing to copy
// we can hotpath via a memcpy. if (result_len == 0 and res_sent_val == null) return mutable_alloc;
if (lhs_ty.zigTypeTag(zcu) == .pointer and if (lhs_ty.zigTypeTag(zcu) == .pointer and
rhs_ty.zigTypeTag(zcu) == .pointer) 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_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_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 lhs_src_pointer = if (lhs_ty.isSlice(zcu))
const rhs_len_ref = try pt.intRef(.usize, rhs_len); try block.addInst(.{
const rhs_dest_offset = try block.addInst(.{ .tag = .slice_ptr,
.tag = .ptr_add, .data = .{ .ty_op = .{
.data = .{ .ty_pl = .{ .ty = many_ty_ref,
.ty = Air.internedToRef(many_ty.toIntern()), .operand = lhs,
.payload = try sema.addExtra(Air.Bin{ } },
.lhs = many_alloc, })
.rhs = lhs_len_ref, else
}), lhs;
} }, _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs_src_pointer);
}); }
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,
}),
} },
});
_ = 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| { if (res_sent_val) |sent_val| {
const elem_index = try pt.intRef(.usize, result_len); 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")); 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" { test "array init with mult" {
if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest;
if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO