| ... | @@ -251,6 +251,31 @@ pub const DeclGen = struct { | ... | @@ -251,6 +251,31 @@ pub const DeclGen = struct { |
| 251 | // error values will be #defined at the top of the file | 251 | // error values will be #defined at the top of the file |
| 252 | return writer.print("zig_error_{s}", .{payload.data.name}); | 252 | return writer.print("zig_error_{s}", .{payload.data.name}); |
| 253 | }, | 253 | }, |
| | 254 | .ErrorUnion => { |
| | 255 | const error_type = t.errorUnionSet(); |
| | 256 | const payload_type = t.errorUnionChild(); |
| | 257 | const data = val.castTag(.error_union).?.data; |
| | 258 | try writer.writeByte('('); |
| | 259 | try dg.renderType(writer, t); |
| | 260 | try writer.writeAll("){"); |
| | 261 | if (val.getError()) |_| { |
| | 262 | try writer.writeAll(" .error = "); |
| | 263 | try dg.renderValue( |
| | 264 | writer, |
| | 265 | error_type, |
| | 266 | data, |
| | 267 | ); |
| | 268 | try writer.writeAll(" }"); |
| | 269 | } else { |
| | 270 | try writer.writeAll(" .payload = "); |
| | 271 | try dg.renderValue( |
| | 272 | writer, |
| | 273 | payload_type, |
| | 274 | data, |
| | 275 | ); |
| | 276 | try writer.writeAll(", .error = 0 }"); |
| | 277 | } |
| | 278 | }, |
| 254 | else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{ | 279 | else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{ |
| 255 | @tagName(e), | 280 | @tagName(e), |
| 256 | }), | 281 | }), |
| ... | @@ -385,16 +410,17 @@ pub const DeclGen = struct { | ... | @@ -385,16 +410,17 @@ pub const DeclGen = struct { |
| 385 | return w.writeAll(some.name); | 410 | return w.writeAll(some.name); |
| 386 | } | 411 | } |
| 387 | const child_type = t.errorUnionChild(); | 412 | const child_type = t.errorUnionChild(); |
| | 413 | const set_type = t.errorUnionSet(); |
| 388 | | 414 | |
| 389 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); | 415 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 390 | defer buffer.deinit(); | 416 | defer buffer.deinit(); |
| 391 | const bw = buffer.writer(); | 417 | const bw = buffer.writer(); |
| 392 | | 418 | |
| 393 | try bw.writeAll("typedef struct { "); | 419 | try bw.writeAll("typedef struct { "); |
| 394 | try dg.renderType(bw, t.errorUnionChild()); | 420 | try dg.renderType(bw, child_type); |
| 395 | try bw.writeAll(" payload; uint16_t error; } "); | 421 | try bw.writeAll(" payload; uint16_t error; } "); |
| 396 | const name_index = buffer.items.len; | 422 | const name_index = buffer.items.len; |
| 397 | try bw.print("zig_err_union_{s}_t;\n", .{typeToCIdentifier(child_type)}); | 423 | try bw.print("zig_err_union_{s}_{s}_t;\n", .{ typeToCIdentifier(set_type), typeToCIdentifier(child_type) }); |
| 398 | | 424 | |
| 399 | const rendered = buffer.toOwnedSlice(); | 425 | const rendered = buffer.toOwnedSlice(); |
| 400 | errdefer dg.typedefs.allocator.free(rendered); | 426 | errdefer dg.typedefs.allocator.free(rendered); |
| ... | @@ -543,6 +569,12 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi | ... | @@ -543,6 +569,12 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi |
| 543 | .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload).?), | 569 | .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload).?), |
| 544 | .is_err => try genIsErr(o, inst.castTag(.is_err).?), | 570 | .is_err => try genIsErr(o, inst.castTag(.is_err).?), |
| 545 | .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?), | 571 | .is_err_ptr => try genIsErr(o, inst.castTag(.is_err_ptr).?), |
| | 572 | .unwrap_errunion_payload => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload).?), |
| | 573 | .unwrap_errunion_err => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err).?), |
| | 574 | .unwrap_errunion_payload_ptr => try genUnwrapErrUnionPay(o, inst.castTag(.unwrap_errunion_payload_ptr).?), |
| | 575 | .unwrap_errunion_err_ptr => try genUnwrapErrUnionErr(o, inst.castTag(.unwrap_errunion_err_ptr).?), |
| | 576 | .wrap_errunion_payload => try genWrapErrUnionPay(o, inst.castTag(.wrap_errunion_payload).?), |
| | 577 | .wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?), |
| 546 | else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), | 578 | else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), |
| 547 | }; | 579 | }; |
| 548 | switch (result_value) { | 580 | switch (result_value) { |
| ... | @@ -962,6 +994,35 @@ fn genOptionalPayload(o: *Object, inst: *Inst.UnOp) !CValue { | ... | @@ -962,6 +994,35 @@ fn genOptionalPayload(o: *Object, inst: *Inst.UnOp) !CValue { |
| 962 | return local; | 994 | return local; |
| 963 | } | 995 | } |
| 964 | | 996 | |
| | 997 | // *(E!T) -> E NOT *E |
| | 998 | fn genUnwrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue { |
| | 999 | const writer = o.writer(); |
| | 1000 | const operand = try o.resolveInst(inst.operand); |
| | 1001 | |
| | 1002 | const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else "."; |
| | 1003 | |
| | 1004 | const local = try o.allocLocal(inst.base.ty, .Const); |
| | 1005 | try writer.writeAll(" = ("); |
| | 1006 | try o.writeCValue(writer, operand); |
| | 1007 | |
| | 1008 | try writer.print("){s}error;\n", .{maybe_deref}); |
| | 1009 | return local; |
| | 1010 | } |
| | 1011 | fn genUnwrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue { |
| | 1012 | const writer = o.writer(); |
| | 1013 | const operand = try o.resolveInst(inst.operand); |
| | 1014 | |
| | 1015 | const maybe_deref = if (inst.operand.ty.zigTypeTag() == .Pointer) "->" else "."; |
| | 1016 | const maybe_addrof = if (inst.base.ty.zigTypeTag() == .Pointer) "&" else ""; |
| | 1017 | |
| | 1018 | const local = try o.allocLocal(inst.base.ty, .Const); |
| | 1019 | try writer.print(" = {s}(", .{maybe_addrof}); |
| | 1020 | try o.writeCValue(writer, operand); |
| | 1021 | |
| | 1022 | try writer.print("){s}payload;\n", .{maybe_deref}); |
| | 1023 | return local; |
| | 1024 | } |
| | 1025 | |
| 965 | fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { | 1026 | fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { |
| 966 | const writer = o.writer(); | 1027 | const writer = o.writer(); |
| 967 | const operand = try o.resolveInst(inst.operand); | 1028 | const operand = try o.resolveInst(inst.operand); |
| ... | @@ -978,6 +1039,26 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { | ... | @@ -978,6 +1039,26 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { |
| 978 | try writer.writeAll("};\n"); | 1039 | try writer.writeAll("};\n"); |
| 979 | return local; | 1040 | return local; |
| 980 | } | 1041 | } |
| | 1042 | fn genWrapErrUnionErr(o: *Object, inst: *Inst.UnOp) !CValue { |
| | 1043 | const writer = o.writer(); |
| | 1044 | const operand = try o.resolveInst(inst.operand); |
| | 1045 | |
| | 1046 | const local = try o.allocLocal(inst.base.ty, .Const); |
| | 1047 | try writer.writeAll(" = { .error = "); |
| | 1048 | try o.writeCValue(writer, operand); |
| | 1049 | try writer.writeAll(" };\n"); |
| | 1050 | return local; |
| | 1051 | } |
| | 1052 | fn genWrapErrUnionPay(o: *Object, inst: *Inst.UnOp) !CValue { |
| | 1053 | const writer = o.writer(); |
| | 1054 | const operand = try o.resolveInst(inst.operand); |
| | 1055 | |
| | 1056 | const local = try o.allocLocal(inst.base.ty, .Const); |
| | 1057 | try writer.writeAll(" = { .error = 0, .payload = "); |
| | 1058 | try o.writeCValue(writer, operand); |
| | 1059 | try writer.writeAll(" };\n"); |
| | 1060 | return local; |
| | 1061 | } |
| 981 | | 1062 | |
| 982 | fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue { | 1063 | fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue { |
| 983 | const writer = o.writer(); | 1064 | const writer = o.writer(); |