diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-03-19 15:13:27 +0200 |
|---|---|---|
| committer | Veikka Tuominen <git@vexu.eu> | 2022-03-19 15:49:27 +0200 |
| commit | 12f3c461a4429d9c7a0ddbaa6465bf0499a99b8c (patch) | |
| tree | fbe7dffade76aed2f015c1a9029abe76bf25e590 /src | |
| parent | c9b6f1bf907a0083f1fb0eba2f6969fd8f7f3b64 (diff) | |
| download | zig-12f3c461a4429d9c7a0ddbaa6465bf0499a99b8c.tar.gz zig-12f3c461a4429d9c7a0ddbaa6465bf0499a99b8c.zip | |
Sema: implement zirSwitchCaptureElse for error sets
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 34 | ||||
| -rw-r--r-- | src/link/MachO.zig | 5 | ||||
| -rw-r--r-- | src/link/MachO/DebugSymbols.zig | 1 | ||||
| -rw-r--r-- | src/value.zig | 32 |
4 files changed, 57 insertions, 15 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index f8a5c28b80..94db6e80b9 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -131,6 +131,9 @@ pub const Block = struct { c_import_buf: ?*std.ArrayList(u8) = null, + /// type of `err` in `else => |err|` + switch_else_err_ty: ?Type = null, + const Param = struct { /// `noreturn` means `anytype`. ty: Type, @@ -189,6 +192,7 @@ pub const Block = struct { .runtime_index = parent.runtime_index, .want_safety = parent.want_safety, .c_import_buf = parent.c_import_buf, + .switch_else_err_ty = parent.switch_else_err_ty, }; } @@ -6714,12 +6718,6 @@ fn zirSwitchCapture( if (capture_info.prong_index == std.math.maxInt(@TypeOf(capture_info.prong_index))) { // It is the else/`_` prong. - switch (operand_ty.zigTypeTag()) { - .ErrorSet => { - return sema.fail(block, operand_src, "TODO implement Sema for zirSwitchCaptureElse for error sets", .{}); - }, - else => {}, - } if (is_ref) { assert(operand_is_ref); return operand_ptr; @@ -6730,7 +6728,10 @@ fn zirSwitchCapture( else operand_ptr; - return operand; + switch (operand_ty.zigTypeTag()) { + .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src), + else => return operand, + } } if (is_multi) { @@ -6907,6 +6908,8 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError const operand_ty = sema.typeOf(operand); + var else_error_ty: ?Type = null; + // Validate usage of '_' prongs. if (special_prong == .under and !operand_ty.isNonexhaustiveEnum()) { const msg = msg: { @@ -7099,6 +7102,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError .{}, ); } + else_error_ty = Type.@"anyerror"; } else { var maybe_msg: ?*Module.ErrorMsg = null; errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa); @@ -7143,6 +7147,17 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError .{}, ); } + + const error_names = operand_ty.errorSetNames(); + var names: Module.ErrorSet.NameMap = .{}; + try names.ensureUnusedCapacity(sema.arena, error_names.len); + for (error_names) |error_name| { + if (seen_errors.contains(error_name)) continue; + + names.putAssumeCapacityNoClobber(error_name, {}); + } + + else_error_ty = try Type.Tag.error_set_merged.create(sema.arena, names); } }, .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 .label = &label, .inlining = block.inlining, .is_comptime = block.is_comptime, + .switch_else_err_ty = else_error_ty, }; const merges = &child_block.label.?.merges; defer child_block.instructions.deinit(gpa); @@ -18523,8 +18539,8 @@ pub fn bitCastVal( const abi_size = try sema.usizeCast(block, src, old_ty.abiSize(target)); const buffer = try sema.gpa.alloc(u8, abi_size); defer sema.gpa.free(buffer); - val.writeToMemory(old_ty, target, buffer); - return Value.readFromMemory(new_ty, target, buffer[buffer_offset..], sema.arena); + val.writeToMemory(old_ty, sema.mod, buffer); + return Value.readFromMemory(new_ty, sema.mod, buffer[buffer_offset..], sema.arena); } fn coerceArrayPtrToSlice( diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 694ddc5613..1cab5fe067 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -4301,6 +4301,7 @@ fn populateMissingMetadata(self: *MachO) !void { .inner = .{ .segname = makeStaticString("__PAGEZERO"), .vmsize = pagezero_vmsize, + .cmdsize = @sizeOf(macho.segment_command_64), }, }, }); @@ -4326,6 +4327,7 @@ fn populateMissingMetadata(self: *MachO) !void { .filesize = needed_size, .maxprot = macho.PROT.READ | macho.PROT.EXEC, .initprot = macho.PROT.READ | macho.PROT.EXEC, + .cmdsize = @sizeOf(macho.segment_command_64), }, }, }); @@ -4431,6 +4433,7 @@ fn populateMissingMetadata(self: *MachO) !void { .filesize = needed_size, .maxprot = macho.PROT.READ | macho.PROT.WRITE, .initprot = macho.PROT.READ | macho.PROT.WRITE, + .cmdsize = @sizeOf(macho.segment_command_64), }, }, }); @@ -4480,6 +4483,7 @@ fn populateMissingMetadata(self: *MachO) !void { .filesize = needed_size, .maxprot = macho.PROT.READ | macho.PROT.WRITE, .initprot = macho.PROT.READ | macho.PROT.WRITE, + .cmdsize = @sizeOf(macho.segment_command_64), }, }, }); @@ -4589,6 +4593,7 @@ fn populateMissingMetadata(self: *MachO) !void { .fileoff = fileoff, .maxprot = macho.PROT.READ, .initprot = macho.PROT.READ, + .cmdsize = @sizeOf(macho.segment_command_64), }, }, }); diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index 3d80e9a9b5..9fc2828ea1 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -148,6 +148,7 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: Allocator) !void .vmsize = needed_size, .fileoff = fileoff, .filesize = needed_size, + .cmdsize = @sizeOf(macho.segment_command_64), }, }, }); diff --git a/src/value.zig b/src/value.zig index b45c106c26..8e6afccb60 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1042,7 +1042,8 @@ pub const Value = extern union { }; } - pub fn writeToMemory(val: Value, ty: Type, target: Target, buffer: []u8) void { + pub fn writeToMemory(val: Value, ty: Type, mod: *Module, buffer: []u8) void { + const target = mod.getTarget(); if (val.isUndef()) { const size = @intCast(usize, ty.abiSize(target)); std.mem.set(u8, buffer[0..size], 0xaa); @@ -1081,7 +1082,7 @@ pub const Value = extern union { var buf_off: usize = 0; while (elem_i < len) : (elem_i += 1) { const elem_val = val.elemValueBuffer(elem_i, &elem_value_buf); - writeToMemory(elem_val, elem_ty, target, buffer[buf_off..]); + writeToMemory(elem_val, elem_ty, mod, buffer[buf_off..]); buf_off += elem_size; } }, @@ -1092,7 +1093,7 @@ pub const Value = extern union { const field_vals = val.castTag(.aggregate).?.data; for (fields) |field, i| { const off = @intCast(usize, ty.structFieldOffset(i, target)); - writeToMemory(field_vals[i], field.ty, target, buffer[off..]); + writeToMemory(field_vals[i], field.ty, mod, buffer[off..]); } }, .Packed => { @@ -1105,6 +1106,12 @@ pub const Value = extern union { host_int.writeTwosComplement(buffer, bit_size, abi_size, target.cpu.arch.endian()); }, }, + .ErrorSet => { + // TODO revisit this when we have the concept of the error tag type + const Int = u16; + const int = mod.global_error_set.get(val.castTag(.@"error").?.data.name).?; + std.mem.writeInt(Int, buffer[0..@sizeOf(Int)], @intCast(Int, int), target.cpu.arch.endian()); + }, else => @panic("TODO implement writeToMemory for more types"), } } @@ -1153,10 +1160,11 @@ pub const Value = extern union { pub fn readFromMemory( ty: Type, - target: Target, + mod: *Module, buffer: []const u8, arena: Allocator, ) Allocator.Error!Value { + const target = mod.getTarget(); switch (ty.zigTypeTag()) { .Int => { if (buffer.len == 0) return Value.zero; @@ -1184,7 +1192,7 @@ pub const Value = extern union { const elems = try arena.alloc(Value, @intCast(usize, ty.arrayLen())); var offset: usize = 0; for (elems) |*elem| { - elem.* = try readFromMemory(elem_ty, target, buffer[offset..], arena); + elem.* = try readFromMemory(elem_ty, mod, buffer[offset..], arena); offset += @intCast(usize, elem_size); } return Tag.aggregate.create(arena, elems); @@ -1196,7 +1204,7 @@ pub const Value = extern union { const field_vals = try arena.alloc(Value, fields.len); for (fields) |field, i| { const off = @intCast(usize, ty.structFieldOffset(i, target)); - field_vals[i] = try readFromMemory(field.ty, target, buffer[off..], arena); + field_vals[i] = try readFromMemory(field.ty, mod, buffer[off..], arena); } return Tag.aggregate.create(arena, field_vals); }, @@ -1212,6 +1220,18 @@ pub const Value = extern union { return intToPackedStruct(ty, target, bigint.toConst(), arena); }, }, + .ErrorSet => { + // TODO revisit this when we have the concept of the error tag type + const Int = u16; + const int = std.mem.readInt(Int, buffer[0..@sizeOf(Int)], target.cpu.arch.endian()); + + const payload = try arena.create(Value.Payload.Error); + payload.* = .{ + .base = .{ .tag = .@"error" }, + .data = .{ .name = mod.error_name_list.items[@intCast(usize, int)] }, + }; + return Value.initPayload(&payload.base); + }, else => @panic("TODO implement readFromMemory for more types"), } } |
