authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-20 16:35:24+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-02-22 21:56:34+01:00
logf4f23e307c7a493435bed155359a5f3a2b57d965
tree05eb45a407bf3703148aaf059a84634b8b166c12
parent358b5441570916a48f2f7df9ebe8b9cb5f87676b

codegen: lower error_set and error_union


3 files changed, 52 insertions(+), 6 deletions(-)

src/arch/x86_64/CodeGen.zig+3-6
...@@ -3509,6 +3509,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3509,6 +3509,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3509 return self.fail("TODO isErr for errors with size larger than register size", .{});3509 return self.fail("TODO isErr for errors with size larger than register size", .{});
3510 }3510 }
3511 } else {3511 } else {
3512 log.warn("operand = {}, payload_type = {}", .{ operand, payload_type });
3512 return self.fail("TODO isErr for non-empty payloads", .{});3513 return self.fail("TODO isErr for non-empty payloads", .{});
3513 }3514 }
3514}3515}
...@@ -5108,22 +5109,18 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -5108,22 +5109,18 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
5108 const error_type = typed_value.ty.errorUnionSet();5109 const error_type = typed_value.ty.errorUnionSet();
5109 const payload_type = typed_value.ty.errorUnionPayload();5110 const payload_type = typed_value.ty.errorUnionPayload();
51105111
5111 if (typed_value.val.castTag(.eu_payload)) |pl| {5112 if (typed_value.val.castTag(.eu_payload)) |_| {
5112 if (!payload_type.hasRuntimeBits()) {5113 if (!payload_type.hasRuntimeBits()) {
5113 // We use the error type directly as the type.5114 // We use the error type directly as the type.
5114 return MCValue{ .immediate = 0 };5115 return MCValue{ .immediate = 0 };
5115 }5116 }
5116
5117 _ = pl;
5118 return self.fail("TODO implement error union const of type '{}' (non-error)", .{typed_value.ty});
5119 } else {5117 } else {
5120 if (!payload_type.hasRuntimeBits()) {5118 if (!payload_type.hasRuntimeBits()) {
5121 // We use the error type directly as the type.5119 // We use the error type directly as the type.
5122 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });5120 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });
5123 }5121 }
5124 }5122 }
51255123 return self.lowerUnnamedConst(typed_value);
5126 return self.fail("TODO implement error union const of type '{}' (error)", .{typed_value.ty});
5127 },5124 },
5128 .Struct => {5125 .Struct => {
5129 return self.lowerUnnamedConst(typed_value);5126 return self.lowerUnnamedConst(typed_value);
src/codegen.zig+48
...@@ -432,6 +432,54 @@ pub fn generateSymbol(...@@ -432,6 +432,54 @@ pub fn generateSymbol(
432432
433 return Result{ .appended = {} };433 return Result{ .appended = {} };
434 },434 },
435 .ErrorUnion => {
436 const error_ty = typed_value.ty.errorUnionSet();
437 const payload_ty = typed_value.ty.errorUnionPayload();
438 const is_payload = typed_value.val.errorUnionIsPayload();
439
440 const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero);
441 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
442 .ty = error_ty,
443 .val = error_val,
444 }, code, debug_output)) {
445 .appended => {},
446 .externally_managed => |external_slice| {
447 code.appendSliceAssumeCapacity(external_slice);
448 },
449 .fail => |em| return Result{ .fail = em },
450 }
451
452 if (payload_ty.hasRuntimeBits()) {
453 const payload_val = if (typed_value.val.castTag(.eu_payload)) |val| val.data else Value.initTag(.undef);
454 switch (try generateSymbol(bin_file, parent_atom_index, src_loc, .{
455 .ty = payload_ty,
456 .val = payload_val,
457 }, code, debug_output)) {
458 .appended => {},
459 .externally_managed => |external_slice| {
460 code.appendSliceAssumeCapacity(external_slice);
461 },
462 .fail => |em| return Result{ .fail = em },
463 }
464 }
465
466 return Result{ .appended = {} };
467 },
468 .ErrorSet => {
469 const target = bin_file.options.target;
470 switch (typed_value.val.tag()) {
471 .@"error" => {
472 const name = typed_value.val.getError().?;
473 const kv = try bin_file.options.module.?.getErrorValue(name);
474 const endian = target.cpu.arch.endian();
475 try code.writer().writeInt(u32, kv.value, endian);
476 },
477 else => {
478 try code.writer().writeByteNTimes(0, @intCast(usize, typed_value.ty.abiSize(target)));
479 },
480 }
481 return Result{ .appended = {} };
482 },
435 else => |t| {483 else => |t| {
436 return Result{484 return Result{
437 .fail = try ErrorMsg.create(485 .fail = try ErrorMsg.create(
src/link/Elf.zig+1
...@@ -3127,6 +3127,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl...@@ -3127,6 +3127,7 @@ pub fn lowerUnnamedConst(self: *Elf, typed_value: TypedValue, decl: *Module.Decl
3127 .fail => |em| {3127 .fail => |em| {
3128 decl.analysis = .codegen_failure;3128 decl.analysis = .codegen_failure;
3129 try module.failed_decls.put(module.gpa, decl, em);3129 try module.failed_decls.put(module.gpa, decl, em);
3130 log.err("{s}", .{em.msg});
3130 return error.AnalysisFail;3131 return error.AnalysisFail;
3131 },3132 },
3132 };3133 };