authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-05-24 20:47:45+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-24 15:34:52-07:00
logc847a462ae11e0d483ad877b3ecc9ec291c29bb3
tree1114d6a36b25feba7175d46eabc3f511f227094b
parent26376c9fda910e28a686d3f772dbda4319abc16d

stage2 ARM: update to new union layout


2 files changed, 65 insertions(+), 37 deletions(-)

src/arch/arm/CodeGen.zig+64-37
......@@ -3,6 +3,7 @@ const builtin = @import("builtin");
33const mem = std.mem;
44const math = std.math;
55const assert = std.debug.assert;
6const codegen = @import("../../codegen.zig");
67const Air = @import("../../Air.zig");
78const Mir = @import("Mir.zig");
89const Emit = @import("Emit.zig");
......@@ -22,12 +23,14 @@ const leb128 = std.leb;
2223const log = std.log.scoped(.codegen);
2324const build_options = @import("build_options");
2425
25const FnResult = @import("../../codegen.zig").FnResult;
26const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;
27const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
26const FnResult = codegen.FnResult;
27const GenerateSymbolError = codegen.GenerateSymbolError;
28const DebugInfoOutput = codegen.DebugInfoOutput;
2829
2930const bits = @import("bits.zig");
3031const abi = @import("abi.zig");
32const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
33const errUnionErrOffset = codegen.errUnionErrOffset;
3134const RegisterManager = abi.RegisterManager;
3235const RegisterLock = RegisterManager.RegisterLock;
3336const Register = bits.Register;
......@@ -1763,19 +1766,26 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
17631766
17641767/// Given an error union, returns the error
17651768fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
1769 const err_ty = error_union_ty.errorUnionSet();
17661770 const payload_ty = error_union_ty.errorUnionPayload();
1767 if (!payload_ty.hasRuntimeBits()) return error_union_mcv;
1771 if (err_ty.errorSetCardinality() == .zero) {
1772 return MCValue{ .immediate = 0 };
1773 }
1774 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1775 return error_union_mcv;
1776 }
17681777
1778 const err_offset = @intCast(u32, errUnionErrOffset(error_union_ty, self.target.*));
17691779 switch (error_union_mcv) {
17701780 .register => return self.fail("TODO errUnionErr for registers", .{}),
17711781 .stack_argument_offset => |off| {
1772 return MCValue{ .stack_argument_offset = off };
1782 return MCValue{ .stack_argument_offset = off - err_offset };
17731783 },
17741784 .stack_offset => |off| {
1775 return MCValue{ .stack_offset = off };
1785 return MCValue{ .stack_offset = off - err_offset };
17761786 },
17771787 .memory => |addr| {
1778 return MCValue{ .memory = addr };
1788 return MCValue{ .memory = addr + err_offset };
17791789 },
17801790 else => unreachable, // invalid MCValue for an error union
17811791 }
......@@ -1793,24 +1803,26 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
17931803
17941804/// Given an error union, returns the payload
17951805fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
1806 const err_ty = error_union_ty.errorUnionSet();
17961807 const payload_ty = error_union_ty.errorUnionPayload();
1797 if (!payload_ty.hasRuntimeBits()) return MCValue.none;
1798
1799 const error_ty = error_union_ty.errorUnionSet();
1800 const error_size = @intCast(u32, error_ty.abiSize(self.target.*));
1801 const eu_align = @intCast(u32, error_union_ty.abiAlignment(self.target.*));
1802 const offset = std.mem.alignForwardGeneric(u32, error_size, eu_align);
1808 if (err_ty.errorSetCardinality() == .zero) {
1809 return error_union_mcv;
1810 }
1811 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1812 return MCValue.none;
1813 }
18031814
1815 const payload_offset = @intCast(u32, errUnionPayloadOffset(error_union_ty, self.target.*));
18041816 switch (error_union_mcv) {
18051817 .register => return self.fail("TODO errUnionPayload for registers", .{}),
18061818 .stack_argument_offset => |off| {
1807 return MCValue{ .stack_argument_offset = off - offset };
1819 return MCValue{ .stack_argument_offset = off - payload_offset };
18081820 },
18091821 .stack_offset => |off| {
1810 return MCValue{ .stack_offset = off - offset };
1822 return MCValue{ .stack_offset = off - payload_offset };
18111823 },
18121824 .memory => |addr| {
1813 return MCValue{ .memory = addr - offset };
1825 return MCValue{ .memory = addr + payload_offset };
18141826 },
18151827 else => unreachable, // invalid MCValue for an error union
18161828 }
......@@ -3478,6 +3490,9 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
34783490
34793491 switch (self.ret_mcv) {
34803492 .none => {},
3493 .immediate => {
3494 assert(ret_ty.isError());
3495 },
34813496 .register => |reg| {
34823497 // Return result by value
34833498 try self.genSetReg(ret_ty, reg, operand);
......@@ -3867,7 +3882,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
38673882 const error_type = ty.errorUnionSet();
38683883 const error_int_type = Type.initTag(.u16);
38693884
3870 if (!error_type.hasRuntimeBits()) {
3885 if (error_type.errorSetCardinality() == .zero) {
38713886 return MCValue{ .immediate = 0 }; // always false
38723887 }
38733888
......@@ -4975,7 +4990,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
49754990 const ref_int = @enumToInt(inst);
49764991 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
49774992 const tv = Air.Inst.Ref.typed_value_map[ref_int];
4978 if (!tv.ty.hasRuntimeBits()) {
4993 if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) {
49794994 return MCValue{ .none = {} };
49804995 }
49814996 return self.genTypedValue(tv);
......@@ -4983,7 +4998,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
49834998
49844999 // If the type has no codegen bits, no need to store it.
49855000 const inst_ty = self.air.typeOf(inst);
4986 if (!inst_ty.hasRuntimeBits())
5001 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())
49875002 return MCValue{ .none = {} };
49885003
49895004 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
......@@ -5147,26 +5162,35 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
51475162 }
51485163 },
51495164 .ErrorSet => {
5150 const err_name = typed_value.val.castTag(.@"error").?.data.name;
5151 const module = self.bin_file.options.module.?;
5152 const global_error_set = module.global_error_set;
5153 const error_index = global_error_set.get(err_name).?;
5154 return MCValue{ .immediate = error_index };
5165 switch (typed_value.val.tag()) {
5166 .@"error" => {
5167 const err_name = typed_value.val.castTag(.@"error").?.data.name;
5168 const module = self.bin_file.options.module.?;
5169 const global_error_set = module.global_error_set;
5170 const error_index = global_error_set.get(err_name).?;
5171 return MCValue{ .immediate = error_index };
5172 },
5173 else => {
5174 // In this case we are rendering an error union which has a 0 bits payload.
5175 return MCValue{ .immediate = 0 };
5176 },
5177 }
51555178 },
51565179 .ErrorUnion => {
51575180 const error_type = typed_value.ty.errorUnionSet();
51585181 const payload_type = typed_value.ty.errorUnionPayload();
51595182
5160 if (typed_value.val.castTag(.eu_payload)) |_| {
5161 if (!payload_type.hasRuntimeBits()) {
5162 // We use the error type directly as the type.
5163 return MCValue{ .immediate = 0 };
5164 }
5165 } else {
5166 if (!payload_type.hasRuntimeBits()) {
5167 // We use the error type directly as the type.
5168 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });
5169 }
5183 if (error_type.errorSetCardinality() == .zero) {
5184 const payload_val = typed_value.val.castTag(.eu_payload).?.data;
5185 return self.genTypedValue(.{ .ty = payload_type, .val = payload_val });
5186 }
5187
5188 const is_pl = typed_value.val.errorUnionIsPayload();
5189
5190 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
5191 // We use the error type directly as the type.
5192 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
5193 return self.genTypedValue(.{ .ty = error_type, .val = err_val });
51705194 }
51715195 },
51725196
......@@ -5231,7 +5255,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
52315255
52325256 if (ret_ty.zigTypeTag() == .NoReturn) {
52335257 result.return_value = .{ .unreach = {} };
5234 } else if (!ret_ty.hasRuntimeBits()) {
5258 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
52355259 result.return_value = .{ .none = {} };
52365260 } else {
52375261 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
......@@ -5278,11 +5302,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
52785302 .Unspecified => {
52795303 if (ret_ty.zigTypeTag() == .NoReturn) {
52805304 result.return_value = .{ .unreach = {} };
5281 } else if (!ret_ty.hasRuntimeBits()) {
5305 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
52825306 result.return_value = .{ .none = {} };
52835307 } else {
52845308 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
5285 if (ret_ty_size <= 4) {
5309 if (ret_ty_size == 0) {
5310 assert(ret_ty.isError());
5311 result.return_value = .{ .immediate = 0 };
5312 } else if (ret_ty_size <= 4) {
52865313 result.return_value = .{ .register = .r0 };
52875314 } else {
52885315 // The result is returned by reference, not by
test/behavior/error.zig+1
......@@ -441,6 +441,7 @@ test "return function call to error set from error union function" {
441441
442442test "optional error set is the same size as error set" {
443443 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
444 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
444445
445446 comptime try expect(@sizeOf(?anyerror) == @sizeOf(anyerror));
446447 comptime try expect(@alignOf(?anyerror) == @alignOf(anyerror));