From 8c6e7fb2c7488faab0c41a4ea241f0110237ce91 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 29 Jan 2021 12:19:10 +0200 Subject: stage2: implement var args --- src/type.zig | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) (limited to 'src/type.zig') diff --git a/src/type.zig b/src/type.zig index 38fe6dd3e6..bb8dcea390 100644 --- a/src/type.zig +++ b/src/type.zig @@ -97,6 +97,8 @@ pub const Type = extern union { .@"struct", .empty_struct => return .Struct, .@"enum" => return .Enum, .@"union" => return .Union, + + .var_args_param => unreachable, // can be any type } } @@ -258,6 +260,8 @@ pub const Type = extern union { if (!a.fnParamType(i).eql(b.fnParamType(i))) return false; } + if (a.fnIsVarArgs() != b.fnIsVarArgs()) + return false; return true; }, .Optional => { @@ -323,6 +327,7 @@ pub const Type = extern union { while (i < params_len) : (i += 1) { std.hash.autoHash(&hasher, self.fnParamType(i).hash()); } + std.hash.autoHash(&hasher, self.fnIsVarArgs()); }, .Optional => { var buf: Payload.ElemType = undefined; @@ -397,6 +402,7 @@ pub const Type = extern union { .@"anyframe", .inferred_alloc_const, .inferred_alloc_mut, + .var_args_param, => unreachable, .array_u8, @@ -446,6 +452,7 @@ pub const Type = extern union { .return_type = try payload.return_type.copy(allocator), .param_types = param_types, .cc = payload.cc, + .is_var_args = payload.is_var_args, }); }, .pointer => { @@ -535,6 +542,7 @@ pub const Type = extern union { .comptime_int, .comptime_float, .noreturn, + .var_args_param, => return out_stream.writeAll(@tagName(t)), .enum_literal => return out_stream.writeAll("@Type(.EnumLiteral)"), @@ -558,6 +566,12 @@ pub const Type = extern union { if (i != 0) try out_stream.writeAll(", "); try param_type.format("", .{}, out_stream); } + if (payload.is_var_args) { + if (payload.param_types.len != 0) { + try out_stream.writeAll(", "); + } + try out_stream.writeAll("..."); + } try out_stream.writeAll(") callconv(."); try out_stream.writeAll(@tagName(payload.cc)); try out_stream.writeAll(")"); @@ -844,6 +858,7 @@ pub const Type = extern union { .inferred_alloc_const => unreachable, .inferred_alloc_mut => unreachable, + .var_args_param => unreachable, }; } @@ -969,6 +984,7 @@ pub const Type = extern union { .inferred_alloc_const, .inferred_alloc_mut, .@"opaque", + .var_args_param, => unreachable, }; } @@ -995,6 +1011,7 @@ pub const Type = extern union { .inferred_alloc_const => unreachable, .inferred_alloc_mut => unreachable, .@"opaque" => unreachable, + .var_args_param => unreachable, .u8, .i8, @@ -1179,6 +1196,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, .single_const_pointer, @@ -1256,6 +1274,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, .const_slice, @@ -1354,6 +1373,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, .const_slice, @@ -1434,6 +1454,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, .single_const_pointer, @@ -1523,6 +1544,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, .pointer => { @@ -1607,6 +1629,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, .pointer => { @@ -1733,6 +1756,7 @@ pub const Type = extern union { .@"struct" => unreachable, .@"union" => unreachable, .@"opaque" => unreachable, + .var_args_param => unreachable, .array => self.castTag(.array).?.data.elem_type, .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type, @@ -1862,6 +1886,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, .array => self.castTag(.array).?.data.len, @@ -1936,6 +1961,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, .single_const_pointer, @@ -2025,6 +2051,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, .int_signed, @@ -2110,6 +2137,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, .int_unsigned, @@ -2181,6 +2209,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, .int_unsigned => .{ @@ -2280,6 +2309,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, .usize, @@ -2400,6 +2430,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, }; } @@ -2486,6 +2517,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, } } @@ -2571,6 +2603,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, } } @@ -2656,6 +2689,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, }; } @@ -2738,6 +2772,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, }; } @@ -2749,7 +2784,7 @@ pub const Type = extern union { .fn_void_no_args => false, .fn_naked_noreturn_no_args => false, .fn_ccc_void_no_args => false, - .function => false, + .function => self.castTag(.function).?.data.is_var_args, .f16, .f32, @@ -2820,6 +2855,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => unreachable, }; } @@ -2902,6 +2938,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => false, }; } @@ -2962,6 +2999,7 @@ pub const Type = extern union { .error_set, .error_set_single, .@"opaque", + .var_args_param, => return null, .@"enum" => @panic("TODO onePossibleValue enum"), @@ -3079,6 +3117,7 @@ pub const Type = extern union { .@"struct", .@"union", .@"opaque", + .var_args_param, => return false, .c_const_pointer, @@ -3168,6 +3207,7 @@ pub const Type = extern union { .pointer, .inferred_alloc_const, .inferred_alloc_mut, + .var_args_param, => unreachable, .empty_struct => self.castTag(.empty_struct).?.data, @@ -3285,6 +3325,9 @@ pub const Type = extern union { anyerror_void_error_union, @"anyframe", const_slice_u8, + /// This is a special type for variadic parameters of a function call. + /// Casts to it will validate that the type can be passed to a c calling convetion function. + var_args_param, /// This is a special value that tracks a set of types that have been stored /// to an inferred allocation. It does not support most of the normal type queries. /// However it does respond to `isConstPtr`, `ptrSize`, `zigTypeTag`, etc. @@ -3373,6 +3416,7 @@ pub const Type = extern union { .const_slice_u8, .inferred_alloc_const, .inferred_alloc_mut, + .var_args_param, => @compileError("Type Tag " ++ @tagName(t) ++ " has no payload"), .array_u8, @@ -3479,6 +3523,7 @@ pub const Type = extern union { param_types: []Type, return_type: Type, cc: std.builtin.CallingConvention, + is_var_args: bool, }, }; -- cgit v1.2.3 From cfc19eace71c92ecd7e138db6d961271a1b6c126 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 29 Jan 2021 18:20:35 +0200 Subject: stage2 cbe: errors --- src/codegen/c.zig | 29 +++++++++++++++++++++++++++++ src/link/C.zig | 13 +++++++++++++ src/type.zig | 12 ++++++++++++ 3 files changed, 54 insertions(+) (limited to 'src/type.zig') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 642166092e..fe87a5994a 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -217,6 +217,11 @@ pub const DeclGen = struct { try writer.writeAll(" }"); } }, + .ErrorSet => { + const payload = val.castTag(.@"error").?; + // error values will be #defined at the top of the file + return writer.print("zig_error_{s}", .{payload.data.name}); + }, else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{ @tagName(e), }), @@ -327,6 +332,16 @@ pub const DeclGen = struct { try dg.renderType(w, child_type); try w.writeAll(" payload; bool is_null; }"); }, + .ErrorSet => { + comptime std.debug.assert(Type.initTag(.anyerror).abiSize(std.Target.current) == 2); + try w.writeAll("uint16_t"); + }, + .ErrorUnion => { + // TODO this needs to be typedeffed since different structs are different types. + try w.writeAll("struct { "); + try dg.renderType(w, t.errorUnionChild()); + try w.writeAll(" payload; uint16_t error; }"); + }, .Null, .Undefined => unreachable, // must be const or comptime else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement type {s}", .{ @tagName(e), @@ -464,6 +479,8 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi .wrap_optional => try genWrapOptional(o, inst.castTag(.wrap_optional).?), .optional_payload => try genOptionalPayload(o, inst.castTag(.optional_payload).?), .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload).?), + .is_err => try genIsErr(o, inst.castTag(.is_err).?), + .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?), else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), }; switch (result_value) { @@ -900,6 +917,18 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { return local; } +fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue { + const writer = o.writer(); + const maybe_deref = if (inst.base.tag == .is_err_ptr) "[0]" else ""; + const operand = try o.resolveInst(inst.operand); + + const local = try o.allocLocal(Type.initTag(.bool), .Const); + try writer.writeAll(" = ("); + try o.writeCValue(writer, operand); + try writer.print("){s}.error != 0;\n", .{maybe_deref}); + return local; +} + fn IndentWriter(comptime UnderlyingWriter: type) type { return struct { const Self = @This(); diff --git a/src/link/C.zig b/src/link/C.zig index 8fb3637cbe..1860fdb051 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -150,6 +150,19 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { .iov_len = zig_h.len, }); + var error_defs_buf = std.ArrayList(u8).init(comp.gpa); + defer error_defs_buf.deinit(); + + var it = module.global_error_set.iterator(); + while (it.next()) |entry| { + try error_defs_buf.writer().print("#define zig_error_{s} {d}\n", .{ entry.key, entry.value }); + } + try error_defs_buf.writer().writeByte('\n'); + all_buffers.appendAssumeCapacity(.{ + .iov_base = error_defs_buf.items.ptr, + .iov_len = error_defs_buf.items.len, + }); + var fn_count: usize = 0; // Forward decls and non-functions first. diff --git a/src/type.zig b/src/type.zig index bb8dcea390..50d55a0c54 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1813,6 +1813,18 @@ pub const Type = extern union { } } + /// Asserts that the type is an error union. + pub fn errorUnionChild(self: Type) Type { + return switch (self.tag()) { + .anyerror_void_error_union => Type.initTag(.anyerror), + .error_union => { + const payload = self.castTag(.error_union).?; + return payload.data.payload; + }, + else => unreachable, + }; + } + /// Asserts the type is an array or vector. pub fn arrayLen(self: Type) u64 { return switch (self.tag()) { -- cgit v1.2.3 From 6467ef6d3b5648d47c13b877d3d4fe6a5b5efb7d Mon Sep 17 00:00:00 2001 From: jacob gw Date: Mon, 1 Mar 2021 11:25:50 -0500 Subject: cbe: add error comparison support --- src/codegen.zig | 2 ++ src/type.zig | 2 +- src/zir_sema.zig | 3 ++- test/stage2/cbe.zig | 56 ++++++++++++++++++++++++++++++++++------------------- 4 files changed, 41 insertions(+), 22 deletions(-) (limited to 'src/type.zig') diff --git a/src/codegen.zig b/src/codegen.zig index c3cd64cf73..cfe605b567 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -2237,6 +2237,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { // No side effects, so if it's unreferenced, do nothing. if (inst.base.isUnused()) return MCValue{ .dead = {} }; + if (inst.lhs.ty.zigTypeTag() == .ErrorSet or inst.rhs.ty.zigTypeTag() == .ErrorSet) + return self.fail(inst.base.src, "TODO implement cmp for errors", .{}); switch (arch) { .x86_64 => { try self.code.ensureCapacity(self.code.items.len + 8); diff --git a/src/type.zig b/src/type.zig index 50d55a0c54..c3a99bb184 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1663,6 +1663,7 @@ pub const Type = extern union { .Int, .Float, .ErrorSet, + .ErrorUnion, .Enum, .Frame, .AnyFrame, @@ -1687,7 +1688,6 @@ pub const Type = extern union { }, .Pointer, .Array => ty = ty.elemType(), - .ErrorUnion => @panic("TODO fn isValidVarType"), .Fn => @panic("TODO fn isValidVarType"), .Struct => @panic("TODO struct isValidVarType"), .Union => @panic("TODO union isValidVarType"), diff --git a/src/zir_sema.zig b/src/zir_sema.zig index 9cbdfd07dd..a1b79879b8 100644 --- a/src/zir_sema.zig +++ b/src/zir_sema.zig @@ -2326,7 +2326,8 @@ fn zirCmp( return mod.constBool(scope, inst.base.src, std.mem.eql(u8, lval.castTag(.@"error").?.data.name, rval.castTag(.@"error").?.data.name) == (op == .eq)); } } - return mod.fail(scope, inst.base.src, "TODO implement equality comparison between runtime errors", .{}); + const b = try mod.requireRuntimeBlock(scope, inst.base.src); + return mod.addBinOp(b, inst.base.src, Type.initTag(.bool), if (op == .eq) .cmp_eq else .cmp_neq, lhs, rhs); } else if (lhs.ty.isNumeric() and rhs.ty.isNumeric()) { // This operation allows any combination of integer and float types, regardless of the // signed-ness, comptime-ness, and bit-width. So peer type resolution is incorrect for diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index ba679f49a0..1487b15e12 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -244,30 +244,46 @@ pub fn addCases(ctx: *TestContext) !void { \\} , ""); } - { - var case = ctx.exeFromCompiledC("optionals", .{}); + //{ + // var case = ctx.exeFromCompiledC("optionals", .{}); - // Simple while loop - case.addCompareOutput( - \\export fn main() c_int { - \\ var count: c_int = 0; - \\ var opt_ptr: ?*c_int = &count; - \\ while (opt_ptr) |_| : (count += 1) { - \\ if (count == 4) opt_ptr = null; - \\ } - \\ return count - 5; - \\} - , ""); + // // Simple while loop + // case.addCompareOutput( + // \\export fn main() c_int { + // \\ var count: c_int = 0; + // \\ var opt_ptr: ?*c_int = &count; + // \\ while (opt_ptr) |_| : (count += 1) { + // \\ if (count == 4) opt_ptr = null; + // \\ } + // \\ return count - 5; + // \\} + // , ""); - // Same with non pointer optionals + // // Same with non pointer optionals + // case.addCompareOutput( + // \\export fn main() c_int { + // \\ var count: c_int = 0; + // \\ var opt_ptr: ?c_int = count; + // \\ while (opt_ptr) |_| : (count += 1) { + // \\ if (count == 4) opt_ptr = null; + // \\ } + // \\ return count - 5; + // \\} + // , ""); + //} + { + var case = ctx.exeFromCompiledC("errors", .{}); case.addCompareOutput( \\export fn main() c_int { - \\ var count: c_int = 0; - \\ var opt_ptr: ?c_int = count; - \\ while (opt_ptr) |_| : (count += 1) { - \\ if (count == 4) opt_ptr = null; - \\ } - \\ return count - 5; + \\ var e1 = error.Foo; + \\ var e2 = error.Bar; + \\ assert(e1 != e2); + \\ assert(e1 == error.Foo); + \\ assert(e2 == error.Bar); + \\ return 0; + \\} + \\fn assert(b: bool) void { + \\ if (!b) unreachable; \\} , ""); } -- cgit v1.2.3 From 30ffa052f2b53d9a01aedbe672bec3c5e28d5118 Mon Sep 17 00:00:00 2001 From: jacob gw Date: Mon, 1 Mar 2021 15:16:18 -0500 Subject: stage2 cbe: add error union and error union operations --- src/codegen/c.zig | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++-- src/link/C.zig | 3 +- src/type.zig | 11 +++++++ test/stage2/cbe.zig | 14 +++++++++ 4 files changed, 110 insertions(+), 3 deletions(-) (limited to 'src/type.zig') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 084c653d1c..ceafe01d35 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -251,6 +251,31 @@ pub const DeclGen = struct { // error values will be #defined at the top of the file return writer.print("zig_error_{s}", .{payload.data.name}); }, + .ErrorUnion => { + const error_type = t.errorUnionSet(); + const payload_type = t.errorUnionChild(); + const data = val.castTag(.error_union).?.data; + try writer.writeByte('('); + try dg.renderType(writer, t); + try writer.writeAll("){"); + if (val.getError()) |_| { + try writer.writeAll(" .error = "); + try dg.renderValue( + writer, + error_type, + data, + ); + try writer.writeAll(" }"); + } else { + try writer.writeAll(" .payload = "); + try dg.renderValue( + writer, + payload_type, + data, + ); + try writer.writeAll(", .error = 0 }"); + } + }, else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{ @tagName(e), }), @@ -385,16 +410,17 @@ pub const DeclGen = struct { return w.writeAll(some.name); } const child_type = t.errorUnionChild(); + const set_type = t.errorUnionSet(); var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); defer buffer.deinit(); const bw = buffer.writer(); try bw.writeAll("typedef struct { "); - try dg.renderType(bw, t.errorUnionChild()); + try dg.renderType(bw, child_type); try bw.writeAll(" payload; uint16_t error; } "); const name_index = buffer.items.len; - try bw.print("zig_err_union_{s}_t;\n", .{typeToCIdentifier(child_type)}); + try bw.print("zig_err_union_{s}_{s}_t;\n", .{ typeToCIdentifier(set_type), typeToCIdentifier(child_type) }); const rendered = buffer.toOwnedSlice(); errdefer dg.typedefs.allocator.free(rendered); @@ -543,6 +569,12 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload).?), .is_err => try genIsErr(o, inst.castTag(.is_err).?), .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?), + .unwrap_errunion_payload => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload).?), + .unwrap_errunion_err => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err).?), + .unwrap_errunion_payload_ptr => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload_ptr).?), + .unwrap_errunion_err_ptr => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err_ptr).?), + .wrap_errunion_payload => try genWrapErrUnionPay(o, inst.castTag(.wrap_errunion_payload).?), + .wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?), else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), }; switch (result_value) { @@ -962,6 +994,35 @@ fn genOptionalPayload(o: *Object, inst: *Inst.UnOp) !CValue { return local; } +// *(E!T) -> E NOT *E +fn genUnwrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue { + const writer = o.writer(); + const operand = try o.resolveInst(inst.operand); + + const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else "."; + + const local = try o.allocLocal(inst.base.ty, .Const); + try writer.writeAll(" = ("); + try o.writeCValue(writer, operand); + + try writer.print("){s}error;\n", .{maybe_deref}); + return local; +} +fn genUnwrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue { + const writer = o.writer(); + const operand = try o.resolveInst(inst.operand); + + const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else "."; + const maybe_addrof = if (inst.base.ty.zigTypeTag() == .Pointer) "&" else ""; + + const local = try o.allocLocal(inst.base.ty, .Const); + try writer.print(" = {s}(", .{maybe_addrof}); + try o.writeCValue(writer, operand); + + try writer.print("){s}payload;\n", .{maybe_deref}); + return local; +} + fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { const writer = o.writer(); const operand = try o.resolveInst(inst.operand); @@ -978,6 +1039,26 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { try writer.writeAll("};\n"); return local; } +fn genWrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue { + const writer = o.writer(); + const operand = try o.resolveInst(inst.operand); + + const local = try o.allocLocal(inst.base.ty, .Const); + try writer.writeAll(" = { .error = "); + try o.writeCValue(writer, operand); + try writer.writeAll(" };\n"); + return local; +} +fn genWrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue { + const writer = o.writer(); + const operand = try o.resolveInst(inst.operand); + + const local = try o.allocLocal(inst.base.ty, .Const); + try writer.writeAll(" = { .error = 0, .payload = "); + try o.writeCValue(writer, operand); + try writer.writeAll(" };\n"); + return local; +} fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue { const writer = o.writer(); diff --git a/src/link/C.zig b/src/link/C.zig index 60844ce43b..655a044394 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -179,7 +179,8 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { if (module.global_error_set.size == 0) break :render_errors; var it = module.global_error_set.iterator(); while (it.next()) |entry| { - try err_typedef_writer.print("#define zig_error_{s} {d}\n", .{ entry.key, entry.value }); + // + 1 because 0 represents no error + try err_typedef_writer.print("#define zig_error_{s} {d}\n", .{ entry.key, entry.value + 1 }); } try err_typedef_writer.writeByte('\n'); } diff --git a/src/type.zig b/src/type.zig index c3a99bb184..b9f9207d4a 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1825,6 +1825,17 @@ pub const Type = extern union { }; } + pub fn errorUnionSet(self: Type) Type { + return switch (self.tag()) { + .anyerror_void_error_union => Type.initTag(.anyerror), + .error_union => { + const payload = self.castTag(.error_union).?; + return payload.data.error_set; + }, + else => unreachable, + }; + } + /// Asserts the type is an array or vector. pub fn arrayLen(self: Type) u64 { return switch (self.tag()) { diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index 1487b15e12..e9082f57fa 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -286,6 +286,20 @@ pub fn addCases(ctx: *TestContext) !void { \\ if (!b) unreachable; \\} , ""); + case.addCompareOutput( + \\export fn main() c_int { + \\ var e: anyerror!c_int = 0; + \\ const i = e catch 69; + \\ return i; + \\} + , ""); + case.addCompareOutput( + \\export fn main() c_int { + \\ var e: anyerror!c_int = error.Foo; + \\ const i = e catch 69; + \\ return 69 - i; + \\} + , ""); } ctx.c("empty start function", linux_x64, \\export fn _start() noreturn { -- cgit v1.2.3 From fc62ff77c3921758624a81970f3098300992ee47 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Mon, 1 Mar 2021 23:03:26 +0200 Subject: stage2: error union payload must also be a valid variable type --- src/codegen/c.zig | 2 +- src/type.zig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/type.zig') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index ceafe01d35..af8d2d272d 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -566,7 +566,7 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi .is_non_null_ptr => try genIsNull(o, inst.castTag(.is_non_null_ptr).?), .wrap_optional => try genWrapOptional(o, inst.castTag(.wrap_optional).?), .optional_payload => try genOptionalPayload(o, inst.castTag(.optional_payload).?), - .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload).?), + .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload_ptr).?), .is_err => try genIsErr(o, inst.castTag(.is_err).?), .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?), .unwrap_errunion_payload => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload).?), diff --git a/src/type.zig b/src/type.zig index b9f9207d4a..9599a165fd 100644 --- a/src/type.zig +++ b/src/type.zig @@ -1663,7 +1663,6 @@ pub const Type = extern union { .Int, .Float, .ErrorSet, - .ErrorUnion, .Enum, .Frame, .AnyFrame, @@ -1687,6 +1686,7 @@ pub const Type = extern union { return ty.optionalChild(&buf).isValidVarType(is_extern); }, .Pointer, .Array => ty = ty.elemType(), + .ErrorUnion => ty = ty.errorUnionChild(), .Fn => @panic("TODO fn isValidVarType"), .Struct => @panic("TODO struct isValidVarType"), -- cgit v1.2.3