authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-15 19:21:58-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-15 19:21:58-07:00
log9a6fa67cbc7e5771f3770c0cb7d6d2c6bafb6957
tree4ee6f2f8ebf858321d970b2da9e7191475827c6e
parentfd43434149658ee482428714e05722e5a12fdecc

Sema: only do store_ptr tuple optimization for arrays

Check the big comment in the diff for more details. Fixes default-initialization of structs from empty struct literals.

3 files changed, 17 insertions(+), 4 deletions(-)

src/Sema.zig+7-3
...@@ -17578,10 +17578,13 @@ fn storePtr2(...@@ -17578,10 +17578,13 @@ fn storePtr2(
17578 // To generate better code for tuples, we detect a tuple operand here, and17578 // To generate better code for tuples, we detect a tuple operand here, and
17579 // analyze field loads and stores directly. This avoids an extra allocation + memcpy17579 // analyze field loads and stores directly. This avoids an extra allocation + memcpy
17580 // which would occur if we used `coerce`.17580 // which would occur if we used `coerce`.
17581 // However, we avoid this mechanism if the destination element type is17581 // However, we avoid this mechanism if the destination element type is a tuple,
17582 // the same tuple as the source, because the regular store will be better for this case.17582 // because the regular store will be better for this case.
17583 // If the destination type is a struct we don't want this mechanism to trigger, because
17584 // this code does not handle tuple-to-struct coercion which requires dealing with missing
17585 // fields.
17583 const operand_ty = sema.typeOf(uncasted_operand);17586 const operand_ty = sema.typeOf(uncasted_operand);
17584 if (operand_ty.isTuple() and !elem_ty.eql(operand_ty)) {17587 if (operand_ty.isTuple() and elem_ty.zigTypeTag() == .Array) {
17585 const tuple = operand_ty.tupleFields();17588 const tuple = operand_ty.tupleFields();
17586 for (tuple.types) |_, i_usize| {17589 for (tuple.types) |_, i_usize| {
17587 const i = @intCast(u32, i_usize);17590 const i = @intCast(u32, i_usize);
...@@ -17595,6 +17598,7 @@ fn storePtr2(...@@ -17595,6 +17598,7 @@ fn storePtr2(
17595 }17598 }
1759617599
17597 // TODO do the same thing for anon structs as for tuples above.17600 // TODO do the same thing for anon structs as for tuples above.
17601 // However, beware of the need to handle missing/extra fields.
1759817602
17599 // Detect if we are storing an array operand to a bitcasted vector pointer.17603 // Detect if we are storing an array operand to a bitcasted vector pointer.
17600 // If so, we instead reach through the bitcasted pointer to the vector pointer,17604 // If so, we instead reach through the bitcasted pointer to the vector pointer,
test/behavior/struct.zig+9
...@@ -1281,3 +1281,12 @@ test "typed init through error unions and optionals" {...@@ -1281,3 +1281,12 @@ test "typed init through error unions and optionals" {
1281 try S.doTheTest();1281 try S.doTheTest();
1282 comptime try S.doTheTest();1282 comptime try S.doTheTest();
1283}1283}
1284
1285test "initialize struct with empty literal" {
1286 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1287 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1288
1289 const S = struct { x: i32 = 1234 };
1290 var s: S = .{};
1291 try expect(s.x == 1234);
1292}
test/behavior/union.zig+1-1
...@@ -1092,7 +1092,7 @@ test "@unionInit on union with tag but no fields" {...@@ -1092,7 +1092,7 @@ test "@unionInit on union with tag but no fields" {
1092 }1092 }
10931093
1094 fn doTheTest() !void {1094 fn doTheTest() !void {
1095 var data: Data = .{ .no_op = .{} };1095 var data: Data = .{ .no_op = {} };
1096 _ = data;1096 _ = data;
1097 var o = Data.decode(&[_]u8{});1097 var o = Data.decode(&[_]u8{});
1098 try expectEqual(Type.no_op, o);1098 try expectEqual(Type.no_op, o);