diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-04-28 22:27:50 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-28 22:27:50 +0300 |
| commit | 091fe78337dc3ca340fdf74ca6c1a58c5e666626 (patch) | |
| tree | 3f29858b4c6425073e8c14c27d5355ef863f8074 | |
| parent | 3052597a734f87727fa7f1a0e92247f100df3e96 (diff) | |
| parent | f8940a05aeb347deb858b848e33f73ef285c3298 (diff) | |
| download | zig-091fe78337dc3ca340fdf74ca6c1a58c5e666626.tar.gz zig-091fe78337dc3ca340fdf74ca6c1a58c5e666626.zip | |
Merge pull request #11541 from Vexu/stage2-slice-field-ptr
Stage2: fix slice field modification at comptime
| -rw-r--r-- | src/Sema.zig | 131 | ||||
| -rw-r--r-- | src/TypedValue.zig | 41 | ||||
| -rw-r--r-- | src/value.zig | 12 | ||||
| -rw-r--r-- | test/behavior/slice.zig | 11 |
4 files changed, 151 insertions, 44 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 3fa0353e9d..c9d8f090ae 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16979,44 +16979,44 @@ fn fieldPtr( const buf = try sema.arena.create(Type.SlicePtrFieldTypeBuffer); const slice_ptr_ty = inner_ty.slicePtrFieldType(buf); - if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| { - var anon_decl = try block.startAnonDecl(src); - defer anon_decl.deinit(); - - return sema.analyzeDeclRef(try anon_decl.finish( - try slice_ptr_ty.copy(anon_decl.arena()), - try val.slicePtr().copy(anon_decl.arena()), - 0, // default alignment - )); - } - try sema.requireRuntimeBlock(block, src); - const result_ty = try Type.ptr(sema.arena, sema.mod, .{ .pointee_type = slice_ptr_ty, .mutable = object_ptr_ty.ptrIsMutable(), .@"addrspace" = object_ptr_ty.ptrAddressSpace(), }); - return block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr); - } else if (mem.eql(u8, field_name, "len")) { if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| { - var anon_decl = try block.startAnonDecl(src); - defer anon_decl.deinit(); - - return sema.analyzeDeclRef(try anon_decl.finish( - Type.usize, - try Value.Tag.int_u64.create(anon_decl.arena(), val.sliceLen(sema.mod)), - 0, // default alignment - )); + return sema.addConstant( + result_ty, + try Value.Tag.field_ptr.create(sema.arena, .{ + .container_ptr = val, + .container_ty = inner_ty, + .field_index = Value.Payload.Slice.ptr_index, + }), + ); } try sema.requireRuntimeBlock(block, src); + return block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr); + } else if (mem.eql(u8, field_name, "len")) { const result_ty = try Type.ptr(sema.arena, sema.mod, .{ .pointee_type = Type.usize, .mutable = object_ptr_ty.ptrIsMutable(), .@"addrspace" = object_ptr_ty.ptrAddressSpace(), }); + if (try sema.resolveDefinedValue(block, object_ptr_src, inner_ptr)) |val| { + return sema.addConstant( + result_ty, + try Value.Tag.field_ptr.create(sema.arena, .{ + .container_ptr = val, + .container_ty = inner_ty, + .field_index = Value.Payload.Slice.len_index, + }), + ); + } + try sema.requireRuntimeBlock(block, src); + return block.addTyOp(.ptr_slice_len_ptr, result_ty, inner_ptr); } else { return sema.fail( @@ -19297,7 +19297,6 @@ fn beginComptimePtrMutation( const field_ptr = ptr_val.castTag(.field_ptr).?.data; var parent = try beginComptimePtrMutation(sema, block, src, field_ptr.container_ptr); const field_index = @intCast(u32, field_ptr.field_index); - const field_ty = parent.ty.structFieldType(field_index); switch (parent.val.tag()) { .undef => { // A struct or union has been initialized to undefined at comptime and now we @@ -19316,7 +19315,7 @@ fn beginComptimePtrMutation( return ComptimePtrMutationKit{ .decl_ref_mut = parent.decl_ref_mut, .val = &fields[field_index], - .ty = field_ty, + .ty = parent.ty.structFieldType(field_index), }; }, .Union => { @@ -19331,16 +19330,37 @@ fn beginComptimePtrMutation( return ComptimePtrMutationKit{ .decl_ref_mut = parent.decl_ref_mut, .val = &payload.data.val, - .ty = field_ty, + .ty = parent.ty.structFieldType(field_index), }; }, + .Pointer => { + assert(parent.ty.isSlice()); + parent.val.* = try Value.Tag.slice.create(arena, .{ + .ptr = Value.undef, + .len = Value.undef, + }); + + switch (field_index) { + Value.Payload.Slice.ptr_index => return ComptimePtrMutationKit{ + .decl_ref_mut = parent.decl_ref_mut, + .val = &parent.val.castTag(.slice).?.data.ptr, + .ty = parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), + }, + Value.Payload.Slice.len_index => return ComptimePtrMutationKit{ + .decl_ref_mut = parent.decl_ref_mut, + .val = &parent.val.castTag(.slice).?.data.len, + .ty = Type.usize, + }, + else => unreachable, + } + }, else => unreachable, } }, .aggregate => return ComptimePtrMutationKit{ .decl_ref_mut = parent.decl_ref_mut, .val = &parent.val.castTag(.aggregate).?.data[field_index], - .ty = field_ty, + .ty = parent.ty.structFieldType(field_index), }, .@"union" => { // We need to set the active field of the union. @@ -19353,9 +19373,22 @@ fn beginComptimePtrMutation( return ComptimePtrMutationKit{ .decl_ref_mut = parent.decl_ref_mut, .val = &payload.val, - .ty = field_ty, + .ty = parent.ty.structFieldType(field_index), }; }, + .slice => switch (field_index) { + Value.Payload.Slice.ptr_index => return ComptimePtrMutationKit{ + .decl_ref_mut = parent.decl_ref_mut, + .val = &parent.val.castTag(.slice).?.data.ptr, + .ty = parent.ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), + }, + Value.Payload.Slice.len_index => return ComptimePtrMutationKit{ + .decl_ref_mut = parent.decl_ref_mut, + .val = &parent.val.castTag(.slice).?.data.len, + .ty = Type.usize, + }, + else => unreachable, + }, else => unreachable, } @@ -19555,7 +19588,6 @@ fn beginComptimePtrLoad( .field_ptr => blk: { const field_ptr = ptr_val.castTag(.field_ptr).?.data; const field_index = @intCast(u32, field_ptr.field_index); - const field_ty = field_ptr.container_ty.structFieldType(field_index); var deref = try beginComptimePtrLoad(sema, block, src, field_ptr.container_ptr, field_ptr.container_ty); if (field_ptr.container_ty.hasWellDefinedLayout()) { @@ -19570,19 +19602,38 @@ fn beginComptimePtrLoad( deref.ty_without_well_defined_layout = field_ptr.container_ty; } - if (deref.pointee) |*tv| { - const coerce_in_mem_ok = - (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or - (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok; - if (coerce_in_mem_ok) { - deref.pointee = TypedValue{ - .ty = field_ty, - .val = tv.val.fieldValue(tv.ty, field_index), - }; - break :blk deref; - } + const tv = &(deref.pointee orelse { + deref.pointee = null; + break :blk deref; + }); + const coerce_in_mem_ok = + (try sema.coerceInMemoryAllowed(block, field_ptr.container_ty, tv.ty, false, target, src, src)) == .ok or + (try sema.coerceInMemoryAllowed(block, tv.ty, field_ptr.container_ty, false, target, src, src)) == .ok; + if (!coerce_in_mem_ok) { + deref.pointee = null; + break :blk deref; + } + + if (field_ptr.container_ty.isSlice()) { + const slice_val = tv.val.castTag(.slice).?.data; + deref.pointee = switch (field_index) { + Value.Payload.Slice.ptr_index => TypedValue{ + .ty = field_ptr.container_ty.slicePtrFieldType(try sema.arena.create(Type.SlicePtrFieldTypeBuffer)), + .val = slice_val.ptr, + }, + Value.Payload.Slice.len_index => TypedValue{ + .ty = Type.usize, + .val = slice_val.len, + }, + else => unreachable, + }; + } else { + const field_ty = field_ptr.container_ty.structFieldType(field_index); + deref.pointee = TypedValue{ + .ty = field_ty, + .val = tv.val.fieldValue(tv.ty, field_index), + }; } - deref.pointee = null; break :blk deref; }, diff --git a/src/TypedValue.zig b/src/TypedValue.zig index b0d5d77010..43c26b254e 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -146,7 +146,8 @@ pub fn print( if (ty.zigTypeTag() == .Struct) { try writer.writeAll(".{ "); const struct_fields = ty.structFields(); - const max_len = std.math.min(struct_fields.count(), max_aggregate_items); + const len = struct_fields.count(); + const max_len = std.math.min(len, max_aggregate_items); const field_names = struct_fields.keys(); const fields = struct_fields.values(); @@ -160,11 +161,15 @@ pub fn print( .val = vals[i], }, writer, level - 1, mod); } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } return writer.writeAll(" }"); } else { try writer.writeAll(".{ "); const elem_ty = ty.elemType2(); - const max_len = std.math.min(ty.arrayLen(), max_aggregate_items); + const len = ty.arrayLen(); + const max_len = std.math.min(len, max_aggregate_items); var i: u32 = 0; while (i < max_len) : (i += 1) { @@ -174,6 +179,9 @@ pub fn print( .val = vals[i], }, writer, level - 1, mod); } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } return writer.writeAll(" }"); } }, @@ -292,10 +300,15 @@ pub fn print( .ty = ty.elemType2(), .val = val.castTag(.repeated).?.data, }; - while (i < max_aggregate_items) : (i += 1) { + const len = ty.arrayLen(); + const max_len = std.math.min(len, max_aggregate_items); + while (i < max_len) : (i += 1) { if (i != 0) try writer.writeAll(", "); try print(elem_tv, writer, level - 1, mod); } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } return writer.writeAll(" }"); }, .empty_array_sentinel => { @@ -309,7 +322,27 @@ pub fn print( }, writer, level - 1, mod); return writer.writeAll(" }"); }, - .slice => return writer.writeAll("(slice)"), + .slice => { + const payload = val.castTag(.slice).?.data; + try writer.writeAll(".{ "); + const elem_ty = ty.elemType2(); + const len = payload.len.toUnsignedInt(target); + const max_len = std.math.min(len, max_aggregate_items); + + var i: u32 = 0; + while (i < max_len) : (i += 1) { + if (i != 0) try writer.writeAll(", "); + var buf: Value.ElemValueBuffer = undefined; + try print(.{ + .ty = elem_ty, + .val = payload.ptr.elemValueBuffer(mod, i, &buf), + }, writer, level - 1, mod); + } + if (len > max_aggregate_items) { + try writer.writeAll(", ..."); + } + return writer.writeAll(" }"); + }, .float_16 => return writer.print("{}", .{val.castTag(.float_16).?.data}), .float_32 => return writer.print("{}", .{val.castTag(.float_32).?.data}), .float_64 => return writer.print("{}", .{val.castTag(.float_64).?.data}), diff --git a/src/value.zig b/src/value.zig index d2de389de9..adfe4600f8 100644 --- a/src/value.zig +++ b/src/value.zig @@ -2539,6 +2539,15 @@ pub const Value = extern union { return 1; } }, + .decl_ref_mut => { + const decl_index = val.castTag(.decl_ref_mut).?.data.decl_index; + const decl = mod.declPtr(decl_index); + if (decl.ty.zigTypeTag() == .Array) { + return decl.ty.arrayLen(); + } else { + return 1; + } + }, else => unreachable, }; } @@ -5067,6 +5076,9 @@ pub const Value = extern union { ptr: Value, len: Value, }, + + pub const ptr_index = 0; + pub const len_index = 1; }; pub const Ty = struct { diff --git a/test/behavior/slice.zig b/test/behavior/slice.zig index 09d15e3ac5..18c769f27c 100644 --- a/test/behavior/slice.zig +++ b/test/behavior/slice.zig @@ -682,3 +682,14 @@ test "slicing slice with sentinel as end index" { try S.do(); comptime try S.do(); } + +test "slice len modification at comptime" { + comptime { + var buf: [10]u8 = .{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + var items: []u8 = buf[0..0]; + items.len += 2; + try expect(items.len == 2); + try expect(items[0] == 0); + try expect(items[1] == 1); + } +} |
