authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-25 21:35:04-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-25 21:35:04-04:00
log600c7fe1dacc1d6fd35275c7abe459b5b56bfa63
tree5996d60fac39b10502dddf88e0ea3dae8f81520d
parent1c33ea2c35e9260babedb116ad527256e0a4ef5e
parent2f326f24dd812281e321ec03aee3a8150201d389
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11299 from Vexu/stage2-build

stage2 fixes on the way to `zig2 build --help` working

6 files changed, 159 insertions(+), 32 deletions(-)

src/Sema.zig+77-29
......@@ -6945,6 +6945,12 @@ fn zirSwitchCapture(
69456945 const operand_ptr = sema.resolveInst(cond_info.operand);
69466946 const operand_ptr_ty = sema.typeOf(operand_ptr);
69476947 const operand_ty = if (operand_is_ref) operand_ptr_ty.childType() else operand_ptr_ty;
6948 const target = sema.mod.getTarget();
6949
6950 const operand = if (operand_is_ref)
6951 try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src)
6952 else
6953 operand_ptr;
69486954
69496955 if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) {
69506956 // It is the else/`_` prong.
......@@ -6953,42 +6959,57 @@ fn zirSwitchCapture(
69536959 return operand_ptr;
69546960 }
69556961
6956 const operand = if (operand_is_ref)
6957 try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src)
6958 else
6959 operand_ptr;
6960
69616962 switch (operand_ty.zigTypeTag()) {
69626963 .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src),
69636964 else => return operand,
69646965 }
69656966 }
69666967
6967 if (is_multi) {
6968 return sema.fail(block, switch_src, "TODO implement Sema for switch capture multi", .{});
6969 }
6970 const scalar_prong = switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index);
6971 const item = sema.resolveInst(scalar_prong.item);
6972 // Previous switch validation ensured this will succeed
6973 const item_val = sema.resolveConstValue(block, .unneeded, item) catch unreachable;
6974 const target = sema.mod.getTarget();
6968 const items = if (is_multi)
6969 switch_extra.data.getMultiProng(sema.code, switch_extra.end, capture_info.prong_index).items
6970 else
6971 &[_]Zir.Inst.Ref{
6972 switch_extra.data.getScalarProng(sema.code, switch_extra.end, capture_info.prong_index).item,
6973 };
69756974
69766975 switch (operand_ty.zigTypeTag()) {
69776976 .Union => {
69786977 const union_obj = operand_ty.cast(Type.Payload.Union).?.data;
69796978 const enum_ty = union_obj.tag_ty;
69806979
6981 const field_index_usize = enum_ty.enumTagFieldIndex(item_val, target).?;
6982 const field_index = @intCast(u32, field_index_usize);
6983 const field = union_obj.fields.values()[field_index];
6980 const first_item = sema.resolveInst(items[0]);
6981 // Previous switch validation ensured this will succeed
6982 const first_item_val = sema.resolveConstValue(block, .unneeded, first_item) catch unreachable;
6983
6984 const first_field_index = @intCast(u32, enum_ty.enumTagFieldIndex(first_item_val, target).?);
6985 const first_field = union_obj.fields.values()[first_field_index];
69846986
6985 // TODO handle multiple union tags which have compatible types
6987 for (items[1..]) |item| {
6988 const item_ref = sema.resolveInst(item);
6989 // Previous switch validation ensured this will succeed
6990 const item_val = sema.resolveConstValue(block, .unneeded, item_ref) catch unreachable;
6991
6992 const field_index = enum_ty.enumTagFieldIndex(item_val, target).?;
6993 const field = union_obj.fields.values()[field_index];
6994 if (!field.ty.eql(first_field.ty, target)) {
6995 const first_item_src = switch_src; // TODO better source location
6996 const item_src = switch_src;
6997 const msg = msg: {
6998 const msg = try sema.errMsg(block, switch_src, "capture group with incompatible types", .{});
6999 errdefer msg.destroy(sema.gpa);
7000 try sema.errNote(block, first_item_src, msg, "type '{}' here", .{first_field.ty.fmt(target)});
7001 try sema.errNote(block, item_src, msg, "type '{}' here", .{field.ty.fmt(target)});
7002 break :msg msg;
7003 };
7004 return sema.failWithOwnedErrorMsg(block, msg);
7005 }
7006 }
69867007
69877008 if (is_ref) {
69887009 assert(operand_is_ref);
69897010
69907011 const field_ty_ptr = try Type.ptr(sema.arena, target, .{
6991 .pointee_type = field.ty,
7012 .pointee_type = first_field.ty,
69927013 .@"addrspace" = .generic,
69937014 .mutable = operand_ptr_ty.ptrIsMutable(),
69947015 });
......@@ -6999,30 +7020,48 @@ fn zirSwitchCapture(
69997020 try Value.Tag.field_ptr.create(sema.arena, .{
70007021 .container_ptr = op_ptr_val,
70017022 .container_ty = operand_ty,
7002 .field_index = field_index,
7023 .field_index = first_field_index,
70037024 }),
70047025 );
70057026 }
70067027 try sema.requireRuntimeBlock(block, operand_src);
7007 return block.addStructFieldPtr(operand_ptr, field_index, field_ty_ptr);
7028 return block.addStructFieldPtr(operand_ptr, first_field_index, field_ty_ptr);
70087029 }
70097030
7010 const operand = if (operand_is_ref)
7011 try sema.analyzeLoad(block, operand_src, operand_ptr, operand_src)
7012 else
7013 operand_ptr;
7014
70157031 if (try sema.resolveDefinedValue(block, operand_src, operand)) |operand_val| {
70167032 return sema.addConstant(
7017 field.ty,
7033 first_field.ty,
70187034 operand_val.castTag(.@"union").?.data.val,
70197035 );
70207036 }
70217037 try sema.requireRuntimeBlock(block, operand_src);
7022 return block.addStructFieldVal(operand, field_index, field.ty);
7038 return block.addStructFieldVal(operand, first_field_index, first_field.ty);
70237039 },
70247040 .ErrorSet => {
7025 return sema.fail(block, operand_src, "TODO implement Sema for zirSwitchCapture for error sets", .{});
7041 if (is_multi) {
7042 var names: Module.ErrorSet.NameMap = .{};
7043 try names.ensureUnusedCapacity(sema.arena, items.len);
7044 for (items) |item| {
7045 const item_ref = sema.resolveInst(item);
7046 // Previous switch validation ensured this will succeed
7047 const item_val = sema.resolveConstValue(block, .unneeded, item_ref) catch unreachable;
7048 names.putAssumeCapacityNoClobber(
7049 item_val.getError().?,
7050 {},
7051 );
7052 }
7053 // names must be sorted
7054 Module.ErrorSet.sortNames(&names);
7055 const else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
7056
7057 return sema.bitCast(block, else_error_ty, operand, operand_src);
7058 } else {
7059 // Previous switch validation ensured this will succeed
7060 const item_val = sema.resolveConstValue(block, .unneeded, items[0]) catch unreachable;
7061
7062 const item_ty = try Type.Tag.error_set_single.create(sema.arena, item_val.getError().?);
7063 return sema.bitCast(block, item_ty, operand, operand_src);
7064 }
70267065 },
70277066 else => {
70287067 return sema.fail(block, operand_src, "switch on type '{}' provides no capture value", .{
......@@ -7390,6 +7429,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
73907429 names.putAssumeCapacityNoClobber(error_name, {});
73917430 }
73927431
7432 // names must be sorted
7433 Module.ErrorSet.sortNames(&names);
73937434 else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
73947435 }
73957436 },
......@@ -7743,6 +7784,9 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
77437784 }
77447785
77457786 if (scalar_cases_len + multi_cases_len == 0) {
7787 if (special_prong == .none) {
7788 return sema.fail(block, src, "switch must handle all possibilities", .{});
7789 }
77467790 return sema.resolveBlockBody(block, src, &child_block, special.body, inst, merges);
77477791 }
77487792
......@@ -12233,7 +12277,9 @@ fn zirStructInit(
1223312277 return alloc;
1223412278 }
1223512279
12236 return sema.fail(block, src, "TODO: Sema.zirStructInit for runtime-known union values", .{});
12280 try sema.requireRuntimeBlock(block, src);
12281 try sema.queueFullTypeResolution(resolved_ty);
12282 return block.addUnionInit(resolved_ty, field_index, init_inst);
1223712283 }
1223812284 unreachable;
1223912285}
......@@ -12976,6 +13022,8 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1297613022 );
1297713023 }
1297813024
13025 // names must be sorted
13026 Module.ErrorSet.sortNames(&names);
1297913027 const ty = try Type.Tag.error_set_merged.create(sema.arena, names);
1298013028 return sema.addType(ty);
1298113029 },
src/Zir.zig+47
......@@ -2620,6 +2620,53 @@ pub const Inst = struct {
26202620 };
26212621 }
26222622 }
2623
2624 pub const MultiProng = struct {
2625 items: []const Ref,
2626 body: []const Index,
2627 };
2628
2629 pub fn getMultiProng(
2630 self: SwitchBlock,
2631 zir: Zir,
2632 extra_end: usize,
2633 prong_index: usize,
2634 ) MultiProng {
2635 // +1 for self.bits.has_multi_cases == true
2636 var extra_index: usize = extra_end + 1;
2637
2638 if (self.bits.specialProng() != .none) {
2639 const body_len = zir.extra[extra_index];
2640 extra_index += 1;
2641 const body = zir.extra[extra_index..][0..body_len];
2642 extra_index += body.len;
2643 }
2644
2645 var scalar_i: usize = 0;
2646 while (scalar_i < self.bits.scalar_cases_len) : (scalar_i += 1) {
2647 extra_index += 1;
2648 const body_len = zir.extra[extra_index];
2649 extra_index += 1;
2650 extra_index += body_len;
2651 }
2652 var multi_i: u32 = 0;
2653 while (true) : (multi_i += 1) {
2654 const items_len = zir.extra[extra_index];
2655 extra_index += 2;
2656 const body_len = zir.extra[extra_index];
2657 extra_index += 1;
2658 const items = zir.refSlice(extra_index, items_len);
2659 extra_index += items_len;
2660 const body = zir.extra[extra_index..][0..body_len];
2661 extra_index += body_len;
2662
2663 if (multi_i < prong_index) continue;
2664 return .{
2665 .items = items,
2666 .body = body,
2667 };
2668 }
2669 }
26232670 };
26242671
26252672 pub const Field = struct {
src/type.zig+5-1
......@@ -4511,7 +4511,11 @@ pub const Type = extern union {
45114511 .enum_full => {
45124512 const enum_full = ty.castTag(.enum_full).?.data;
45134513 if (enum_full.fields.count() == 1) {
4514 return enum_full.values.keys()[0];
4514 if (enum_full.values.count() == 0) {
4515 return Value.zero;
4516 } else {
4517 return enum_full.values.keys()[0];
4518 }
45154519 } else {
45164520 return null;
45174521 }
test/behavior/switch.zig+6-2
......@@ -465,7 +465,10 @@ test "else prong of switch on error set excludes other cases" {
465465}
466466
467467test "switch prongs with error set cases make a new error set type for capture value" {
468 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
468 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
469 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
470 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
471 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
469472
470473 const S = struct {
471474 fn doTheTest() !void {
......@@ -538,7 +541,8 @@ test "switch with null and T peer types and inferred result location type" {
538541}
539542
540543test "switch prongs with cases with identical payload types" {
541 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
544 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
545 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
542546
543547 const Union = union(enum) {
544548 A: usize,
test/behavior/type.zig+7
......@@ -260,6 +260,13 @@ test "Type.ErrorSet" {
260260 .{ .name = "C" },
261261 },
262262 });
263 _ = @Type(.{
264 .ErrorSet = &.{
265 .{ .name = "C" },
266 .{ .name = "B" },
267 .{ .name = "A" },
268 },
269 });
263270}
264271
265272test "Type.Struct" {
test/behavior/union.zig+17
......@@ -1132,3 +1132,20 @@ test "global variable struct contains union initialized to non-most-aligned fiel
11321132 T.s.u.a += 1;
11331133 try expect(T.s.u.a == 4);
11341134}
1135
1136test "union with no result loc initiated with a runtime value" {
1137 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1138 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1139 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1140 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1141
1142 const U = union {
1143 a: u32,
1144 b: u32,
1145 fn foo(u: @This()) void {
1146 _ = u;
1147 }
1148 };
1149 var a: u32 = 1;
1150 U.foo(U{ .a = a });
1151}