| author | |
| committer | |
| log | 562ac8be48e4a08358da73e556e331e3618f8b4b |
| tree | 3495e59a81924c3a8ff12b8948fe069f01f104cc |
| parent | b47e54ed3f6e5d93fff8a2327c88c903cc0a194c |
| signature |
Closes #130687 files changed, 83 insertions(+), 18 deletions(-)
src/arch/wasm/CodeGen.zig+8| ... | @@ -2289,6 +2289,14 @@ fn lowerParentPtr(self: *Self, ptr_val: Value, ptr_child_ty: Type) InnerError!WV | ... | @@ -2289,6 +2289,14 @@ fn lowerParentPtr(self: *Self, ptr_val: Value, ptr_child_ty: Type) InnerError!WV |
| 2289 | const offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align)); | 2289 | const offset = @intCast(u32, std.mem.alignForwardGeneric(u64, layout.tag_size, layout.tag_align)); |
| 2290 | break :blk offset; | 2290 | break :blk offset; |
| 2291 | }, | 2291 | }, |
| 2292 | .Pointer => switch (parent_ty.ptrSize()) { | ||
| 2293 | .Slice => switch (field_ptr.field_index) { | ||
| 2294 | 0 => 0, | ||
| 2295 | 1 => self.ptrSize(), | ||
| 2296 | else => unreachable, | ||
| 2297 | }, | ||
| 2298 | else => unreachable, | ||
| 2299 | }, | ||
| 2292 | else => unreachable, | 2300 | else => unreachable, |
| 2293 | }; | 2301 | }; |
| 2294 | 2302 |
src/codegen.zig+12-2| ... | @@ -363,11 +363,21 @@ pub fn generateSymbol( | ... | @@ -363,11 +363,21 @@ pub fn generateSymbol( |
| 363 | const mod = bin_file.options.module.?; | 363 | const mod = bin_file.options.module.?; |
| 364 | const decl = mod.declPtr(decl_index); | 364 | const decl = mod.declPtr(decl_index); |
| 365 | const addend = blk: { | 365 | const addend = blk: { |
| 366 | switch (decl.ty.tag()) { | 366 | switch (decl.ty.zigTypeTag()) { |
| 367 | .@"struct" => { | 367 | .Struct => { |
| 368 | const addend = decl.ty.structFieldOffset(field_ptr.field_index, target); | 368 | const addend = decl.ty.structFieldOffset(field_ptr.field_index, target); |
| 369 | break :blk @intCast(u32, addend); | 369 | break :blk @intCast(u32, addend); |
| 370 | }, | 370 | }, |
| 371 | .Pointer => { | ||
| 372 | assert(decl.ty.isSlice()); | ||
| 373 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | ||
| 374 | const addend = switch (field_ptr.field_index) { | ||
| 375 | 0 => 0, | ||
| 376 | 1 => decl.ty.slicePtrFieldType(&buf).abiSize(target), | ||
| 377 | else => unreachable, | ||
| 378 | }; | ||
| 379 | break :blk @intCast(u32, addend); | ||
| 380 | }, | ||
| 371 | else => return Result{ | 381 | else => return Result{ |
| 372 | .fail = try ErrorMsg.create( | 382 | .fail = try ErrorMsg.create( |
| 373 | bin_file.allocator, | 383 | bin_file.allocator, |
src/codegen/c.zig+22-12| ... | @@ -485,14 +485,24 @@ pub const DeclGen = struct { | ... | @@ -485,14 +485,24 @@ pub const DeclGen = struct { |
| 485 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; | 485 | const field_ptr = ptr_val.castTag(.field_ptr).?.data; |
| 486 | const container_ty = field_ptr.container_ty; | 486 | const container_ty = field_ptr.container_ty; |
| 487 | const index = field_ptr.field_index; | 487 | const index = field_ptr.field_index; |
| 488 | const field_name = switch (container_ty.zigTypeTag()) { | 488 | const FieldInfo = struct { name: []const u8, ty: Type }; |
| 489 | .Struct => container_ty.structFields().keys()[index], | 489 | const field_info: FieldInfo = switch (container_ty.zigTypeTag()) { |
| 490 | .Union => container_ty.unionFields().keys()[index], | 490 | .Struct => .{ |
| 491 | else => unreachable, | 491 | .name = container_ty.structFields().keys()[index], |
| 492 | }; | 492 | .ty = container_ty.structFields().values()[index].ty, |
| 493 | const field_ty = switch (container_ty.zigTypeTag()) { | 493 | }, |
| 494 | .Struct => container_ty.structFields().values()[index].ty, | 494 | .Union => .{ |
| 495 | .Union => container_ty.unionFields().values()[index].ty, | 495 | .name = container_ty.unionFields().keys()[index], |
| 496 | .ty = container_ty.unionFields().values()[index].ty, | ||
| 497 | }, | ||
| 498 | .Pointer => switch (container_ty.ptrSize()) { | ||
| 499 | .Slice => switch (index) { | ||
| 500 | 0 => FieldInfo{ .name = "ptr", .ty = container_ty.childType() }, | ||
| 501 | 1 => FieldInfo{ .name = "len", .ty = Type.usize }, | ||
| 502 | else => unreachable, | ||
| 503 | }, | ||
| 504 | else => unreachable, | ||
| 505 | }, | ||
| 496 | else => unreachable, | 506 | else => unreachable, |
| 497 | }; | 507 | }; |
| 498 | var container_ptr_ty_pl: Type.Payload.ElemType = .{ | 508 | var container_ptr_ty_pl: Type.Payload.ElemType = .{ |
| ... | @@ -501,16 +511,16 @@ pub const DeclGen = struct { | ... | @@ -501,16 +511,16 @@ pub const DeclGen = struct { |
| 501 | }; | 511 | }; |
| 502 | const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base); | 512 | const container_ptr_ty = Type.initPayload(&container_ptr_ty_pl.base); |
| 503 | 513 | ||
| 504 | if (field_ty.hasRuntimeBitsIgnoreComptime()) { | 514 | if (field_info.ty.hasRuntimeBitsIgnoreComptime()) { |
| 505 | try writer.writeAll("&("); | 515 | try writer.writeAll("&("); |
| 506 | try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty); | 516 | try dg.renderParentPtr(writer, field_ptr.container_ptr, container_ptr_ty); |
| 507 | if (field_ptr.container_ty.tag() == .union_tagged or field_ptr.container_ty.tag() == .union_safety_tagged) { | 517 | if (field_ptr.container_ty.tag() == .union_tagged or field_ptr.container_ty.tag() == .union_safety_tagged) { |
| 508 | try writer.print(")->payload.{ }", .{fmtIdent(field_name)}); | 518 | try writer.print(")->payload.{ }", .{fmtIdent(field_info.name)}); |
| 509 | } else { | 519 | } else { |
| 510 | try writer.print(")->{ }", .{fmtIdent(field_name)}); | 520 | try writer.print(")->{ }", .{fmtIdent(field_info.name)}); |
| 511 | } | 521 | } |
| 512 | } else { | 522 | } else { |
| 513 | try dg.renderParentPtr(writer, field_ptr.container_ptr, field_ty); | 523 | try dg.renderParentPtr(writer, field_ptr.container_ptr, field_info.ty); |
| 514 | } | 524 | } |
| 515 | }, | 525 | }, |
| 516 | .elem_ptr => { | 526 | .elem_ptr => { |
src/codegen/llvm.zig+9| ... | @@ -3938,6 +3938,15 @@ pub const DeclGen = struct { | ... | @@ -3938,6 +3938,15 @@ pub const DeclGen = struct { |
| 3938 | const parent_llvm_ty = try dg.lowerType(parent_ty); | 3938 | const parent_llvm_ty = try dg.lowerType(parent_ty); |
| 3939 | break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); | 3939 | break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); |
| 3940 | }, | 3940 | }, |
| 3941 | .Pointer => { | ||
| 3942 | assert(parent_ty.isSlice()); | ||
| 3943 | const indices: [2]*llvm.Value = .{ | ||
| 3944 | llvm_u32.constInt(0, .False), | ||
| 3945 | llvm_u32.constInt(field_index, .False), | ||
| 3946 | }; | ||
| 3947 | const parent_llvm_ty = try dg.lowerType(parent_ty); | ||
| 3948 | break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); | ||
| 3949 | }, | ||
| 3941 | else => unreachable, | 3950 | else => unreachable, |
| 3942 | } | 3951 | } |
| 3943 | }, | 3952 | }, |
test/behavior.zig+1| ... | @@ -100,6 +100,7 @@ test { | ... | @@ -100,6 +100,7 @@ test { |
| 100 | _ = @import("behavior/bugs/12928.zig"); | 100 | _ = @import("behavior/bugs/12928.zig"); |
| 101 | _ = @import("behavior/bugs/12945.zig"); | 101 | _ = @import("behavior/bugs/12945.zig"); |
| 102 | _ = @import("behavior/bugs/12984.zig"); | 102 | _ = @import("behavior/bugs/12984.zig"); |
| 103 | _ = @import("behavior/bugs/13068.zig"); | ||
| 103 | _ = @import("behavior/bugs/13128.zig"); | 104 | _ = @import("behavior/bugs/13128.zig"); |
| 104 | _ = @import("behavior/byteswap.zig"); | 105 | _ = @import("behavior/byteswap.zig"); |
| 105 | _ = @import("behavior/byval_arg_var.zig"); | 106 | _ = @import("behavior/byval_arg_var.zig"); |
test/behavior/bugs/13068.zig created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | |||
| 4 | pub const allocator = std.heap.page_allocator; | ||
| 5 | var list = std.ArrayList(u32).init(allocator); | ||
| 6 | |||
| 7 | test { | ||
| 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 10 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 11 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 12 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 13 | |||
| 14 | list.items.len = 0; | ||
| 15 | } | ||
test/behavior/slice.zig+16-4| ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); | ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); |
| 2 | const std = @import("std"); | 2 | const std = @import("std"); |
| 3 | const expect = std.testing.expect; | 3 | const expect = std.testing.expect; |
| 4 | const expectEqualSlices = std.testing.expectEqualSlices; | 4 | const expectEqualSlices = std.testing.expectEqualSlices; |
| 5 | const expectEqualStrings = std.testing.expectEqualStrings; | ||
| 5 | const expectEqual = std.testing.expectEqual; | 6 | const expectEqual = std.testing.expectEqual; |
| 6 | const mem = std.mem; | 7 | const mem = std.mem; |
| 7 | 8 | ||
| ... | @@ -686,8 +687,6 @@ test "slice len modification at comptime" { | ... | @@ -686,8 +687,6 @@ test "slice len modification at comptime" { |
| 686 | } | 687 | } |
| 687 | 688 | ||
| 688 | test "slice field ptr const" { | 689 | test "slice field ptr const" { |
| 689 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 690 | |||
| 691 | const const_slice: []const u8 = "string"; | 690 | const const_slice: []const u8 = "string"; |
| 692 | 691 | ||
| 693 | const const_ptr_const_slice = &const_slice; | 692 | const const_ptr_const_slice = &const_slice; |
| ... | @@ -700,8 +699,6 @@ test "slice field ptr const" { | ... | @@ -700,8 +699,6 @@ test "slice field ptr const" { |
| 700 | } | 699 | } |
| 701 | 700 | ||
| 702 | test "slice field ptr var" { | 701 | test "slice field ptr var" { |
| 703 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 704 | |||
| 705 | var var_slice: []const u8 = "string"; | 702 | var var_slice: []const u8 = "string"; |
| 706 | 703 | ||
| 707 | var var_ptr_var_slice = &var_slice; | 704 | var var_ptr_var_slice = &var_slice; |
| ... | @@ -712,3 +709,18 @@ test "slice field ptr var" { | ... | @@ -712,3 +709,18 @@ test "slice field ptr var" { |
| 712 | try expectEqual(*[]const u8, @TypeOf(&const_ptr_var_slice.*)); | 709 | try expectEqual(*[]const u8, @TypeOf(&const_ptr_var_slice.*)); |
| 713 | try expectEqual(*[*]const u8, @TypeOf(&const_ptr_var_slice.ptr)); | 710 | try expectEqual(*[*]const u8, @TypeOf(&const_ptr_var_slice.ptr)); |
| 714 | } | 711 | } |
| 712 | |||
| 713 | test "global slice field access" { | ||
| 714 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 715 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 716 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 717 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 718 | |||
| 719 | const S = struct { | ||
| 720 | var slice: []const u8 = undefined; | ||
| 721 | }; | ||
| 722 | S.slice = "string"; | ||
| 723 | S.slice.ptr += 1; | ||
| 724 | S.slice.len -= 2; | ||
| 725 | try expectEqualStrings("trin", S.slice); | ||
| 726 | } |