authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-19 15:13:27+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-19 15:49:27+02:00
log12f3c461a4429d9c7a0ddbaa6465bf0499a99b8c
treefbe7dffade76aed2f015c1a9029abe76bf25e590
parentc9b6f1bf907a0083f1fb0eba2f6969fd8f7f3b64

Sema: implement zirSwitchCaptureElse for error sets


9 files changed, 82 insertions(+), 44 deletions(-)

lib/std/builtin.zig+1-3
......@@ -753,9 +753,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
753753 @setCold(true);
754754 // Until self-hosted catches up with stage1 language features, we have a simpler
755755 // default panic function:
756 const panic_works = builtin.zig_backend == .stage1 or
757 (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .linux);
758 if (!panic_works) {
756 if (builtin.zig_backend != .stage1 and builtin.zig_backend != .stage2_llvm) {
759757 while (true) {
760758 @breakpoint();
761759 }
lib/std/c/darwin.zig+10-6
......@@ -624,8 +624,7 @@ pub const pthread_attr_t = extern struct {
624624 __opaque: [56]u8,
625625};
626626
627const pthread_t = std.c.pthread_t;
628pub extern "c" fn pthread_threadid_np(thread: ?pthread_t, thread_id: *u64) c_int;
627pub extern "c" fn pthread_threadid_np(thread: ?std.c.pthread_t, thread_id: *u64) c_int;
629628pub extern "c" fn pthread_setname_np(name: [*:0]const u8) E;
630629pub extern "c" fn pthread_getname_np(thread: std.c.pthread_t, name: [*:0]u8, len: usize) E;
631630
......@@ -921,12 +920,17 @@ pub const siginfo_t = extern struct {
921920
922921/// Renamed from `sigaction` to `Sigaction` to avoid conflict with function name.
923922pub const Sigaction = extern struct {
924 pub const handler_fn = fn (c_int) callconv(.C) void;
925 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
923 pub usingnamespace if (builtin.zig_backend == .stage1) struct {
924 pub const handler_fn = fn (c_int) callconv(.C) void;
925 pub const sigaction_fn = fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
926 } else struct {
927 pub const handler_fn = *const fn (c_int) callconv(.C) void;
928 pub const sigaction_fn = *const fn (c_int, *const siginfo_t, ?*const anyopaque) callconv(.C) void;
929 };
926930
927931 handler: extern union {
928 handler: ?handler_fn,
929 sigaction: ?sigaction_fn,
932 handler: ?Sigaction.handler_fn,
933 sigaction: ?Sigaction.sigaction_fn,
930934 },
931935 mask: sigset_t,
932936 flags: c_uint,
lib/std/heap/general_purpose_allocator.zig+6-18
......@@ -341,15 +341,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
341341 const slot_index = @intCast(SlotIndex, used_bits_byte * 8 + bit_index);
342342 const stack_trace = bucketStackTrace(bucket, size_class, slot_index, .alloc);
343343 const addr = bucket.page + slot_index * size_class;
344 if (builtin.zig_backend == .stage1 or builtin.os.tag == .linux) {
345 log.err("memory address 0x{x} leaked: {s}", .{
346 @ptrToInt(addr), stack_trace,
347 });
348 } else { // TODO
349 log.err("memory address 0x{x} leaked", .{
350 @ptrToInt(addr),
351 });
352 }
344 log.err("memory address 0x{x} leaked: {s}", .{
345 @ptrToInt(addr), stack_trace,
346 });
353347 leaks = true;
354348 }
355349 if (bit_index == math.maxInt(u3))
......@@ -379,15 +373,9 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
379373 while (it.next()) |large_alloc| {
380374 if (config.retain_metadata and large_alloc.freed) continue;
381375 const stack_trace = large_alloc.getStackTrace(.alloc);
382 if (builtin.zig_backend == .stage1 or builtin.os.tag == .linux) {
383 log.err("memory address 0x{x} leaked: {s}", .{
384 @ptrToInt(large_alloc.bytes.ptr), stack_trace,
385 });
386 } else { // TODO
387 log.err("memory address 0x{x} leaked", .{
388 @ptrToInt(large_alloc.bytes.ptr),
389 });
390 }
376 log.err("memory address 0x{x} leaked: {s}", .{
377 @ptrToInt(large_alloc.bytes.ptr), stack_trace,
378 });
391379 leaks = true;
392380 }
393381 return leaks;
lib/std/macho.zig+3-1
......@@ -624,7 +624,9 @@ pub const segment_command_64 = extern struct {
624624 cmd: LC = .SEGMENT_64,
625625
626626 /// includes sizeof section_64 structs
627 cmdsize: u32 = @sizeOf(segment_command_64),
627 cmdsize: u32,
628 // TODO lazy values in stage2
629 // cmdsize: u32 = @sizeOf(segment_command_64),
628630
629631 /// segment name
630632 segname: [16]u8,
src/Sema.zig+25-9
......@@ -131,6 +131,9 @@ pub const Block = struct {
131131
132132 c_import_buf: ?*std.ArrayList(u8) = null,
133133
134 /// type of `err` in `else => |err|`
135 switch_else_err_ty: ?Type = null,
136
134137 const Param = struct {
135138 /// `noreturn` means `anytype`.
136139 ty: Type,
......@@ -189,6 +192,7 @@ pub const Block = struct {
189192 .runtime_index = parent.runtime_index,
190193 .want_safety = parent.want_safety,
191194 .c_import_buf = parent.c_import_buf,
195 .switch_else_err_ty = parent.switch_else_err_ty,
192196 };
193197 }
194198
......@@ -6714,12 +6718,6 @@ fn zirSwitchCapture(
67146718
67156719 if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) {
67166720 // It is the else/`_` prong.
6717 switch (operand_ty.zigTypeTag()) {
6718 .ErrorSet => {
6719 return sema.fail(block, operand_src, "TODO implement Sema for zirSwitchCaptureElse for error sets", .{});
6720 },
6721 else => {},
6722 }
67236721 if (is_ref) {
67246722 assert(operand_is_ref);
67256723 return operand_ptr;
......@@ -6730,7 +6728,10 @@ fn zirSwitchCapture(
67306728 else
67316729 operand_ptr;
67326730
6733 return operand;
6731 switch (operand_ty.zigTypeTag()) {
6732 .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src),
6733 else => return operand,
6734 }
67346735 }
67356736
67366737 if (is_multi) {
......@@ -6907,6 +6908,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
69076908
69086909 const operand_ty = sema.typeOf(operand);
69096910
6911 var else_error_ty: ?Type = null;
6912
69106913 // Validate usage of '_' prongs.
69116914 if (special_prong == .under and !operand_ty.isNonexhaustiveEnum()) {
69126915 const msg = msg: {
......@@ -7099,6 +7102,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
70997102 .{},
71007103 );
71017104 }
7105 else_error_ty = Type.@"anyerror";
71027106 } else {
71037107 var maybe_msg: ?*Module.ErrorMsg = null;
71047108 errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa);
......@@ -7143,6 +7147,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
71437147 .{},
71447148 );
71457149 }
7150
7151 const error_names = operand_ty.errorSetNames();
7152 var names: Module.ErrorSet.NameMap = .{};
7153 try names.ensureUnusedCapacity(sema.arena, error_names.len);
7154 for (error_names) |error_name| {
7155 if (seen_errors.contains(error_name)) continue;
7156
7157 names.putAssumeCapacityNoClobber(error_name, {});
7158 }
7159
7160 else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names);
71467161 }
71477162 },
71487163 .Union => return sema.fail(block, src, "TODO validate switch .Union", .{}),
......@@ -7420,6 +7435,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
74207435 .label = &label,
74217436 .inlining = block.inlining,
74227437 .is_comptime = block.is_comptime,
7438 .switch_else_err_ty = else_error_ty,
74237439 };
74247440 const merges = &child_block.label.?.merges;
74257441 defer child_block.instructions.deinit(gpa);
......@@ -18523,8 +18539,8 @@ pub fn bitCastVal(
1852318539 const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target));
1852418540 const buffer = try sema.gpa.alloc(u8, abi_size);
1852518541 defer sema.gpa.free(buffer);
18526 val.writeToMemory(old_ty, target, buffer);
18527 return Value.readFromMemory(new_ty, target, buffer[buffer_offset..], sema.arena);
18542 val.writeToMemory(old_ty, sema.mod, buffer);
18543 return Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena);
1852818544}
1852918545
1853018546fn coerceArrayPtrToSlice(
src/link/MachO.zig+5
......@@ -4301,6 +4301,7 @@ fn populateMissingMetadata(self: *MachO) !void {
43014301 .inner = .{
43024302 .segname = makeStaticString("__PAGEZERO"),
43034303 .vmsize = pagezero_vmsize,
4304 .cmdsize = @sizeOf(macho.segment_command_64),
43044305 },
43054306 },
43064307 });
......@@ -4326,6 +4327,7 @@ fn populateMissingMetadata(self: *MachO) !void {
43264327 .filesize = needed_size,
43274328 .maxprot = macho.PROT.READ | macho.PROT.EXEC,
43284329 .initprot = macho.PROT.READ | macho.PROT.EXEC,
4330 .cmdsize = @sizeOf(macho.segment_command_64),
43294331 },
43304332 },
43314333 });
......@@ -4431,6 +4433,7 @@ fn populateMissingMetadata(self: *MachO) !void {
44314433 .filesize = needed_size,
44324434 .maxprot = macho.PROT.READ | macho.PROT.WRITE,
44334435 .initprot = macho.PROT.READ | macho.PROT.WRITE,
4436 .cmdsize = @sizeOf(macho.segment_command_64),
44344437 },
44354438 },
44364439 });
......@@ -4480,6 +4483,7 @@ fn populateMissingMetadata(self: *MachO) !void {
44804483 .filesize = needed_size,
44814484 .maxprot = macho.PROT.READ | macho.PROT.WRITE,
44824485 .initprot = macho.PROT.READ | macho.PROT.WRITE,
4486 .cmdsize = @sizeOf(macho.segment_command_64),
44834487 },
44844488 },
44854489 });
......@@ -4589,6 +4593,7 @@ fn populateMissingMetadata(self: *MachO) !void {
45894593 .fileoff = fileoff,
45904594 .maxprot = macho.PROT.READ,
45914595 .initprot = macho.PROT.READ,
4596 .cmdsize = @sizeOf(macho.segment_command_64),
45924597 },
45934598 },
45944599 });
src/link/MachO/DebugSymbols.zig+1
......@@ -148,6 +148,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: Allocator) !void
148148 .vmsize = needed_size,
149149 .fileoff = fileoff,
150150 .filesize = needed_size,
151 .cmdsize = @sizeOf(macho.segment_command_64),
151152 },
152153 },
153154 });
src/value.zig+26-6
......@@ -1042,7 +1042,8 @@ pub const Value = extern union {
10421042 };
10431043 }
10441044
1045 pub fn writeToMemory(val: Value, ty: Type, target: Target, buffer: []u8) void {
1045 pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) void {
1046 const target = mod.getTarget();
10461047 if (val.isUndef()) {
10471048 const size = @intCast(usize, ty.abiSize(target));
10481049 std.mem.set(u8, buffer[0..size], 0xaa);
......@@ -1081,7 +1082,7 @@ pub const Value = extern union {
10811082 var buf_off: usize = 0;
10821083 while (elem_i < len) : (elem_i += 1) {
10831084 const elem_val = val.elemValueBuffer(elem_i, &elem_value_buf);
1084 writeToMemory(elem_val, elem_ty, target, buffer[buf_off..]);
1085 writeToMemory(elem_val, elem_ty, mod, buffer[buf_off..]);
10851086 buf_off += elem_size;
10861087 }
10871088 },
......@@ -1092,7 +1093,7 @@ pub const Value = extern union {
10921093 const field_vals = val.castTag(.aggregate).?.data;
10931094 for (fields) |field, i| {
10941095 const off = @intCast(usize, ty.structFieldOffset(i, target));
1095 writeToMemory(field_vals[i], field.ty, target, buffer[off..]);
1096 writeToMemory(field_vals[i], field.ty, mod, buffer[off..]);
10961097 }
10971098 },
10981099 .Packed => {
......@@ -1105,6 +1106,12 @@ pub const Value = extern union {
11051106 host_int.writeTwosComplement(buffer, bit_size, abi_size, target.cpu.arch.endian());
11061107 },
11071108 },
1109 .ErrorSet => {
1110 // TODO revisit this when we have the concept of the error tag type
1111 const Int = u16;
1112 const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?;
1113 std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), target.cpu.arch.endian());
1114 },
11081115 else => @panic("TODO implement writeToMemory for more types"),
11091116 }
11101117 }
......@@ -1153,10 +1160,11 @@ pub const Value = extern union {
11531160
11541161 pub fn readFromMemory(
11551162 ty: Type,
1156 target: Target,
1163 mod: *Module,
11571164 buffer: []const u8,
11581165 arena: Allocator,
11591166 ) Allocator.Error!Value {
1167 const target = mod.getTarget();
11601168 switch (ty.zigTypeTag()) {
11611169 .Int => {
11621170 if (buffer.len == 0) return Value.zero;
......@@ -1184,7 +1192,7 @@ pub const Value = extern union {
11841192 const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen()));
11851193 var offset: usize = 0;
11861194 for (elems) |*elem| {
1187 elem.* = try readFromMemory(elem_ty, target, buffer[offset..], arena);
1195 elem.* = try readFromMemory(elem_ty, mod, buffer[offset..], arena);
11881196 offset += @intCast(usize, elem_size);
11891197 }
11901198 return Tag.aggregate.create(arena, elems);
......@@ -1196,7 +1204,7 @@ pub const Value = extern union {
11961204 const field_vals = try arena.alloc(Value, fields.len);
11971205 for (fields) |field, i| {
11981206 const off = @intCast(usize, ty.structFieldOffset(i, target));
1199 field_vals[i] = try readFromMemory(field.ty, target, buffer[off..], arena);
1207 field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..], arena);
12001208 }
12011209 return Tag.aggregate.create(arena, field_vals);
12021210 },
......@@ -1212,6 +1220,18 @@ pub const Value = extern union {
12121220 return intToPackedStruct(ty, target, bigint.toConst(), arena);
12131221 },
12141222 },
1223 .ErrorSet => {
1224 // TODO revisit this when we have the concept of the error tag type
1225 const Int = u16;
1226 const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], target.cpu.arch.endian());
1227
1228 const payload = try arena.create(Value.Payload.Error);
1229 payload.* = .{
1230 .base = .{ .tag = .@"error" },
1231 .data = .{ .name = mod.error_name_list.items[@intCast(usize, int)] },
1232 };
1233 return Value.initPayload(&payload.base);
1234 },
12151235 else => @panic("TODO implement readFromMemory for more types"),
12161236 }
12171237 }
test/behavior/switch.zig+5-1
......@@ -430,7 +430,11 @@ test "switch on integer with else capturing expr" {
430430}
431431
432432test "else prong of switch on error set excludes other cases" {
433 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
433 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
434 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
435 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
436 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
437 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
434438
435439 const S = struct {
436440 fn doTheTest() !void {