| ... | ... | @@ -251,6 +251,31 @@ pub const DeclGen = struct { |
| 251 | 251 | // error values will be #defined at the top of the file |
| 252 | 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 | 279 | else => |e| return dg.fail(dg.decl.src(), "TODO: C backend: implement value {s}", .{ |
| 255 | 280 | @tagName(e), |
| 256 | 281 | }), |
| ... | ... | @@ -385,16 +410,17 @@ pub const DeclGen = struct { |
| 385 | 410 | return w.writeAll(some.name); |
| 386 | 411 | } |
| 387 | 412 | const child_type = t.errorUnionChild(); |
| 413 | const set_type = t.errorUnionSet(); |
| 388 | 414 | |
| 389 | 415 | var buffer = std.ArrayList(u8).init(dg.typedefs.allocator); |
| 390 | 416 | defer buffer.deinit(); |
| 391 | 417 | const bw = buffer.writer(); |
| 392 | 418 | |
| 393 | 419 | try bw.writeAll("typedef struct { "); |
| 394 | | try dg.renderType(bw, t.errorUnionChild()); |
| 420 | try dg.renderType(bw, child_type); |
| 395 | 421 | try bw.writeAll(" payload; uint16_t error; } "); |
| 396 | 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 | 425 | const rendered = buffer.toOwnedSlice(); |
| 400 | 426 | errdefer dg.typedefs.allocator.free(rendered); |
| ... | ... | @@ -543,6 +569,12 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi |
| 543 | 569 | .optional_payload_ptr => try genOptionalPayload(o, inst.castTag(.optional_payload).?), |
| 544 | 570 | .is_err => try genIsErr(o, inst.castTag(.is_err).?), |
| 545 | 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 | 578 | else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), |
| 547 | 579 | }; |
| 548 | 580 | switch (result_value) { |
| ... | ... | @@ -962,6 +994,35 @@ fn genOptionalPayload(o: *Object, inst: *Inst.UnOp) !CValue { |
| 962 | 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 | 1026 | fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { |
| 966 | 1027 | const writer = o.writer(); |
| 967 | 1028 | const operand = try o.resolveInst(inst.operand); |
| ... | ... | @@ -978,6 +1039,26 @@ fn genWrapOptional(o: *Object, inst: *Inst.UnOp) !CValue { |
| 978 | 1039 | try writer.writeAll("};\n"); |
| 979 | 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 | 1063 | fn genIsErr(o: *Object, inst: *Inst.UnOp) !CValue { |
| 983 | 1064 | const writer = o.writer(); |