authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-06-29 14:26:23-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-06-29 14:26:23-04:00
log98681b2da070755c29065d21d2ffb17be37d9619
treecf9592ac47d5fd6d10557be65fb9d38c624728ee
parent7cc417644862a9b9523545f4455da7722afc8209
parentc3ae909e935f1548408f2e400464370ee02b7e82
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11958 from ziglang/store-to-inferred-ptr

stage2: fix miscompilations for peer expressions any time they needed coercions to runtime types

9 files changed, 78 insertions(+), 58 deletions(-)

lib/std/priority_queue.zig-15
......@@ -286,7 +286,6 @@ const PQlt = PriorityQueue(u32, void, lessThan);
286286const PQgt = PriorityQueue(u32, void, greaterThan);
287287
288288test "std.PriorityQueue: add and remove min heap" {
289 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
290289 var queue = PQlt.init(testing.allocator, {});
291290 defer queue.deinit();
292291
......@@ -305,7 +304,6 @@ test "std.PriorityQueue: add and remove min heap" {
305304}
306305
307306test "std.PriorityQueue: add and remove same min heap" {
308 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
309307 var queue = PQlt.init(testing.allocator, {});
310308 defer queue.deinit();
311309
......@@ -355,7 +353,6 @@ test "std.PriorityQueue: peek" {
355353}
356354
357355test "std.PriorityQueue: sift up with odd indices" {
358 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
359356 var queue = PQlt.init(testing.allocator, {});
360357 defer queue.deinit();
361358 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
......@@ -370,7 +367,6 @@ test "std.PriorityQueue: sift up with odd indices" {
370367}
371368
372369test "std.PriorityQueue: addSlice" {
373 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
374370 var queue = PQlt.init(testing.allocator, {});
375371 defer queue.deinit();
376372 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
......@@ -403,7 +399,6 @@ test "std.PriorityQueue: fromOwnedSlice trivial case 1" {
403399}
404400
405401test "std.PriorityQueue: fromOwnedSlice" {
406 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest;
407402 const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 };
408403 const heap_items = try testing.allocator.dupe(u32, items[0..]);
409404 var queue = PQlt.fromOwnedSlice(testing.allocator, heap_items[0..], {});
......@@ -416,7 +411,6 @@ test "std.PriorityQueue: fromOwnedSlice" {
416411}
417412
418413test "std.PriorityQueue: add and remove max heap" {
419 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
420414 var queue = PQgt.init(testing.allocator, {});
421415 defer queue.deinit();
422416
......@@ -435,7 +429,6 @@ test "std.PriorityQueue: add and remove max heap" {
435429}
436430
437431test "std.PriorityQueue: add and remove same max heap" {
438 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
439432 var queue = PQgt.init(testing.allocator, {});
440433 defer queue.deinit();
441434
......@@ -476,7 +469,6 @@ test "std.PriorityQueue: iterator" {
476469}
477470
478471test "std.PriorityQueue: remove at index" {
479 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
480472 var queue = PQlt.init(testing.allocator, {});
481473 defer queue.deinit();
482474
......@@ -512,7 +504,6 @@ test "std.PriorityQueue: iterator while empty" {
512504}
513505
514506test "std.PriorityQueue: shrinkAndFree" {
515 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
516507 var queue = PQlt.init(testing.allocator, {});
517508 defer queue.deinit();
518509
......@@ -536,7 +527,6 @@ test "std.PriorityQueue: shrinkAndFree" {
536527}
537528
538529test "std.PriorityQueue: update min heap" {
539 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
540530 var queue = PQlt.init(testing.allocator, {});
541531 defer queue.deinit();
542532
......@@ -552,7 +542,6 @@ test "std.PriorityQueue: update min heap" {
552542}
553543
554544test "std.PriorityQueue: update same min heap" {
555 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
556545 var queue = PQlt.init(testing.allocator, {});
557546 defer queue.deinit();
558547
......@@ -569,7 +558,6 @@ test "std.PriorityQueue: update same min heap" {
569558}
570559
571560test "std.PriorityQueue: update max heap" {
572 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
573561 var queue = PQgt.init(testing.allocator, {});
574562 defer queue.deinit();
575563
......@@ -585,7 +573,6 @@ test "std.PriorityQueue: update max heap" {
585573}
586574
587575test "std.PriorityQueue: update same max heap" {
588 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
589576 var queue = PQgt.init(testing.allocator, {});
590577 defer queue.deinit();
591578
......@@ -602,7 +589,6 @@ test "std.PriorityQueue: update same max heap" {
602589}
603590
604591test "std.PriorityQueue: siftUp in remove" {
605 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
606592 var queue = PQlt.init(testing.allocator, {});
607593 defer queue.deinit();
608594
......@@ -623,7 +609,6 @@ fn contextLessThan(context: []const u32, a: usize, b: usize) Order {
623609const CPQlt = PriorityQueue(usize, []const u32, contextLessThan);
624610
625611test "std.PriorityQueue: add and remove min heap with contextful comparator" {
626 if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; // TODO
627612 const context = [_]u32{ 5, 3, 4, 2, 2, 8, 0 };
628613
629614 var queue = CPQlt.init(testing.allocator, context[0..]);
src/AstGen.zig+1-1
......@@ -10007,7 +10007,7 @@ const GenZir = struct {
1000710007 .inferred_ptr => |ptr| {
1000810008 gz.rl_ty_inst = .none;
1000910009 gz.rl_ptr = ptr;
10010 gz.break_result_loc = parent_rl;
10010 gz.break_result_loc = .{ .block_ptr = gz };
1001110011 },
1001210012
1001310013 .block_ptr => |parent_block_scope| {
src/Sema.zig+1-22
......@@ -3079,28 +3079,6 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com
30793079
30803080 if (var_is_mut) {
30813081 try sema.validateVarType(block, ty_src, final_elem_ty, false);
3082
3083 // The value might have been bitcasted into a comptime only
3084 // pointer type such as `*@Type(.EnumLiteral)` so we must now
3085 // update all the stores to not give backends invalid AIR.
3086
3087 var air_tags = sema.air_instructions.items(.tag);
3088 var air_data = sema.air_instructions.items(.data);
3089 var peer_inst_index: usize = 0;
3090 var i = ptr_inst;
3091 while (i < air_tags.len and peer_inst_index < peer_inst_list.len) : (i += 1) {
3092 if (air_tags[i] != .store) continue;
3093 if (air_data[i].bin_op.rhs == peer_inst_list[peer_inst_index]) {
3094 peer_inst_index += 1;
3095 _ = (try sema.resolveMaybeUndefVal(block, .unneeded, air_data[i].bin_op.rhs)) orelse continue;
3096 const coerced_val = try sema.coerce(block, final_elem_ty, air_data[i].bin_op.rhs, .unneeded);
3097 air_tags = sema.air_instructions.items(.tag);
3098 air_data = sema.air_instructions.items(.data);
3099
3100 air_data[i].bin_op.lhs = ptr;
3101 air_data[i].bin_op.rhs = coerced_val;
3102 }
3103 }
31043082 } else ct: {
31053083 // Detect if the value is comptime known. In such case, the
31063084 // last 3 AIR instructions of the block will look like this:
......@@ -4478,6 +4456,7 @@ fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErro
44784456 .label = &label,
44794457 .inlining = parent_block.inlining,
44804458 .is_comptime = parent_block.is_comptime,
4459 .want_safety = parent_block.want_safety,
44814460 };
44824461
44834462 defer child_block.instructions.deinit(gpa);
src/TypedValue.zig+55-7
......@@ -427,15 +427,63 @@ pub fn print(
427427 },
428428 .eu_payload_ptr => {
429429 try writer.writeAll("&");
430 val = val.castTag(.eu_payload_ptr).?.data.container_ptr;
431 ty = ty.elemType2().errorUnionPayload();
430
431 const data = val.castTag(.eu_payload_ptr).?.data;
432
433 var ty_val: Value.Payload.Ty = .{
434 .base = .{ .tag = .ty },
435 .data = ty,
436 };
437
438 try writer.writeAll("@as(");
439 try print(.{
440 .ty = Type.type,
441 .val = Value.initPayload(&ty_val.base),
442 }, writer, level - 1, mod);
443
444 try writer.writeAll(", &(payload of ");
445
446 var ptr_ty: Type.Payload.ElemType = .{
447 .base = .{ .tag = .single_mut_pointer },
448 .data = data.container_ty,
449 };
450
451 try print(.{
452 .ty = Type.initPayload(&ptr_ty.base),
453 .val = data.container_ptr,
454 }, writer, level - 1, mod);
455
456 try writer.writeAll("))");
457 return;
432458 },
433459 .opt_payload_ptr => {
434 try writer.writeAll("&");
435 val = val.castTag(.opt_payload).?.data;
436 var buf: Type.Payload.ElemType = undefined;
437 ty = ty.elemType2().optionalChild(&buf);
438 return print(.{ .ty = ty, .val = val }, writer, level, mod);
460 const data = val.castTag(.opt_payload_ptr).?.data;
461
462 var ty_val: Value.Payload.Ty = .{
463 .base = .{ .tag = .ty },
464 .data = ty,
465 };
466
467 try writer.writeAll("@as(");
468 try print(.{
469 .ty = Type.type,
470 .val = Value.initPayload(&ty_val.base),
471 }, writer, level - 1, mod);
472
473 try writer.writeAll(", &(payload of ");
474
475 var ptr_ty: Type.Payload.ElemType = .{
476 .base = .{ .tag = .single_mut_pointer },
477 .data = data.container_ty,
478 };
479
480 try print(.{
481 .ty = Type.initPayload(&ptr_ty.base),
482 .val = data.container_ptr,
483 }, writer, level - 1, mod);
484
485 try writer.writeAll("))");
486 return;
439487 },
440488
441489 // TODO these should not appear in this function
src/print_zir.zig+1
......@@ -2217,6 +2217,7 @@ const Writer = struct {
22172217
22182218 fn writeUnreachable(self: *Writer, stream: anytype, inst: Zir.Inst.Index) !void {
22192219 const inst_data = self.code.instructions.items(.data)[inst].@"unreachable";
2220 try stream.writeAll(") ");
22202221 try self.writeSrc(stream, inst_data.src());
22212222 }
22222223
test/behavior/basic.zig-12
......@@ -928,18 +928,6 @@ test "try in labeled block doesn't cast to wrong type" {
928928 _ = s;
929929}
930930
931test "comptime int in switch in catch is casted to correct inferred type" {
932 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
933 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
934
935 var a: error{ A, B }!u64 = 0;
936 var b = a catch |err| switch (err) {
937 error.A => 0,
938 else => unreachable,
939 };
940 _ = b;
941}
942
943931test "vector initialized with array init syntax has proper type" {
944932 comptime {
945933 const actual = -@Vector(4, i32){ 1, 2, 3, 4 };
test/behavior/cast.zig+2
......@@ -812,6 +812,7 @@ test "peer type resolution: error union after non-error" {
812812}
813813
814814test "peer cast *[0]T to E![]const T" {
815 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
815816 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
816817 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
817818 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
......@@ -826,6 +827,7 @@ test "peer cast *[0]T to E![]const T" {
826827}
827828
828829test "peer cast *[0]T to []const T" {
830 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
829831 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
830832 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
831833 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
test/behavior/error.zig+1-1
......@@ -709,7 +709,7 @@ test "simple else prong allowed even when all errors handled" {
709709 }
710710 };
711711 var value = S.foo() catch |err| switch (err) {
712 error.Foo => 255,
712 error.Foo => @as(u8, 255),
713713 else => |e| return e,
714714 };
715715 try expect(value == 255);
test/behavior/if.zig+17
......@@ -111,3 +111,20 @@ test "if prongs cast to expected type instead of peer type resolution" {
111111 try S.doTheTest(false);
112112 comptime try S.doTheTest(false);
113113}
114
115test "if peer expressions inferred optional type" {
116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
117 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
118 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
119
120 var self: []const u8 = "abcdef";
121 var index: usize = 0;
122 var left_index = (index << 1) + 1;
123 var right_index = left_index + 1;
124 var left = if (left_index < self.len) self[left_index] else null;
125 var right = if (right_index < self.len) self[right_index] else null;
126 try expect(left_index < self.len);
127 try expect(right_index < self.len);
128 try expect(left.? == 98);
129 try expect(right.? == 99);
130}