diff --git a/src/Sema.zig b/src/Sema.zig index 5acd2012d5..1ec384809f 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -15226,7 +15226,10 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai if (ptr_addrspace) |ptr_as| { const alloc_ty = try pt.ptrTypeSema(.{ .child = result_ty.toIntern(), - .flags = .{ .address_space = ptr_as }, + .flags = .{ + .address_space = ptr_as, + .is_const = true, + }, }); const alloc = try block.addTy(.alloc, alloc_ty); const elem_ptr_ty = try pt.ptrTypeSema(.{ @@ -15234,6 +15237,76 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai .flags = .{ .address_space = ptr_as }, }); + // if both the source and destination are arrays + // we can hot path via a memcpy. + if (lhs_ty.zigTypeTag(zcu) == .pointer and + rhs_ty.zigTypeTag(zcu) == .pointer) + { + const slice_ty = try pt.ptrTypeSema(.{ + .child = resolved_elem_ty.toIntern(), + .flags = .{ + .size = .Slice, + .address_space = ptr_as, + }, + }); + const many_ty = try pt.ptrTypeSema(.{ + .child = resolved_elem_ty.toIntern(), + .flags = .{ + .size = .Many, + .address_space = ptr_as, + }, + }); + const slice_ty_ref = Air.internedToRef(slice_ty.toIntern()); + + // lhs_dest_slice = dest[0..lhs.len] + const lhs_len_ref = try pt.intRef(Type.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 = alloc, + .rhs = lhs_len_ref, + }), + } }, + }); + _ = try block.addBinOp(.memcpy, lhs_dest_slice, lhs); + + // rhs_dest_slice = dest[lhs.len..][0..rhs.len] + const rhs_len_ref = try pt.intRef(Type.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 = 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, + }), + } }, + }); + + _ = try block.addBinOp(.memcpy, rhs_dest_slice, rhs); + + if (res_sent_val) |sent_val| { + const elem_index = try pt.intRef(Type.usize, result_len); + const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty); + const init = Air.internedToRef((try pt.getCoerced(sent_val, lhs_info.elem_type)).toIntern()); + try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store); + } + + return alloc; + } + var elem_i: u32 = 0; while (elem_i < lhs_len) : (elem_i += 1) { const elem_index = try pt.intRef(Type.usize, elem_i); @@ -15558,7 +15631,10 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai if (ptr_addrspace) |ptr_as| { const alloc_ty = try pt.ptrTypeSema(.{ .child = result_ty.toIntern(), - .flags = .{ .address_space = ptr_as }, + .flags = .{ + .address_space = ptr_as, + .is_const = true, + }, }); const alloc = try block.addTy(.alloc, alloc_ty); const elem_ptr_ty = try pt.ptrTypeSema(.{ diff --git a/test/behavior/eval.zig b/test/behavior/eval.zig index da39b06d92..deeadcbb03 100644 --- a/test/behavior/eval.zig +++ b/test/behavior/eval.zig @@ -786,7 +786,7 @@ test "array concatenation peer resolves element types - pointer" { var a = [2]u3{ 1, 7 }; var b = [3]u8{ 200, 225, 255 }; const c = &a ++ &b; - comptime assert(@TypeOf(c) == *[5]u8); + comptime assert(@TypeOf(c) == *const [5]u8); try expect(c[0] == 1); try expect(c[1] == 7); try expect(c[2] == 200); @@ -822,7 +822,7 @@ test "array concatenation sets the sentinel - pointer" { var a = [2]u3{ 1, 7 }; var b = [3:69]u8{ 200, 225, 255 }; const c = &a ++ &b; - comptime assert(@TypeOf(c) == *[5:69]u8); + comptime assert(@TypeOf(c) == *const [5:69]u8); try expect(c[0] == 1); try expect(c[1] == 7); try expect(c[2] == 200); @@ -858,7 +858,7 @@ test "array multiplication sets the sentinel - pointer" { var a = [2:7]u3{ 1, 6 }; const b = &a ** 2; - comptime assert(@TypeOf(b) == *[4:7]u3); + comptime assert(@TypeOf(b) == *const [4:7]u3); try expect(b[0] == 1); try expect(b[1] == 6); try expect(b[2] == 1);