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");...@@ -3,6 +3,7 @@ const builtin = @import("builtin");
3const mem = std.mem;3const mem = std.mem;
4const math = std.math;4const math = std.math;
5const assert = std.debug.assert;5const assert = std.debug.assert;
6const codegen = @import("../../codegen.zig");
6const Air = @import("../../Air.zig");7const Air = @import("../../Air.zig");
7const Mir = @import("Mir.zig");8const Mir = @import("Mir.zig");
8const Emit = @import("Emit.zig");9const Emit = @import("Emit.zig");
...@@ -22,12 +23,14 @@ const leb128 = std.leb;...@@ -22,12 +23,14 @@ const leb128 = std.leb;
22const log = std.log.scoped(.codegen);23const log = std.log.scoped(.codegen);
23const build_options = @import("build_options");24const build_options = @import("build_options");
2425
25const FnResult = @import("../../codegen.zig").FnResult;26const FnResult = codegen.FnResult;
26const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;27const GenerateSymbolError = codegen.GenerateSymbolError;
27const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;28const DebugInfoOutput = codegen.DebugInfoOutput;
2829
29const bits = @import("bits.zig");30const bits = @import("bits.zig");
30const abi = @import("abi.zig");31const abi = @import("abi.zig");
32const errUnionPayloadOffset = codegen.errUnionPayloadOffset;
33const errUnionErrOffset = codegen.errUnionErrOffset;
31const RegisterManager = abi.RegisterManager;34const RegisterManager = abi.RegisterManager;
32const RegisterLock = RegisterManager.RegisterLock;35const RegisterLock = RegisterManager.RegisterLock;
33const Register = bits.Register;36const Register = bits.Register;
...@@ -1763,19 +1766,26 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -1763,19 +1766,26 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
17631766
1764/// Given an error union, returns the error1767/// Given an error union, returns the error
1765fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {1768fn errUnionErr(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
1769 const err_ty = error_union_ty.errorUnionSet();
1766 const payload_ty = error_union_ty.errorUnionPayload();1770 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.*));
1769 switch (error_union_mcv) {1779 switch (error_union_mcv) {
1770 .register => return self.fail("TODO errUnionErr for registers", .{}),1780 .register => return self.fail("TODO errUnionErr for registers", .{}),
1771 .stack_argument_offset => |off| {1781 .stack_argument_offset => |off| {
1772 return MCValue{ .stack_argument_offset = off };1782 return MCValue{ .stack_argument_offset = off - err_offset };
1773 },1783 },
1774 .stack_offset => |off| {1784 .stack_offset => |off| {
1775 return MCValue{ .stack_offset = off };1785 return MCValue{ .stack_offset = off - err_offset };
1776 },1786 },
1777 .memory => |addr| {1787 .memory => |addr| {
1778 return MCValue{ .memory = addr };1788 return MCValue{ .memory = addr + err_offset };
1779 },1789 },
1780 else => unreachable, // invalid MCValue for an error union1790 else => unreachable, // invalid MCValue for an error union
1781 }1791 }
...@@ -1793,24 +1803,26 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1793,24 +1803,26 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
17931803
1794/// Given an error union, returns the payload1804/// Given an error union, returns the payload
1795fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {1805fn errUnionPayload(self: *Self, error_union_mcv: MCValue, error_union_ty: Type) !MCValue {
1806 const err_ty = error_union_ty.errorUnionSet();
1796 const payload_ty = error_union_ty.errorUnionPayload();1807 const payload_ty = error_union_ty.errorUnionPayload();
1797 if (!payload_ty.hasRuntimeBits()) return MCValue.none;1808 if (err_ty.errorSetCardinality() == .zero) {
17981809 return error_union_mcv;
1799 const error_ty = error_union_ty.errorUnionSet();1810 }
1800 const error_size = @intCast(u32, error_ty.abiSize(self.target.*));1811 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1801 const eu_align = @intCast(u32, error_union_ty.abiAlignment(self.target.*));1812 return MCValue.none;
1802 const offset = std.mem.alignForwardGeneric(u32, error_size, eu_align);1813 }
18031814
1815 const payload_offset = @intCast(u32, errUnionPayloadOffset(error_union_ty, self.target.*));
1804 switch (error_union_mcv) {1816 switch (error_union_mcv) {
1805 .register => return self.fail("TODO errUnionPayload for registers", .{}),1817 .register => return self.fail("TODO errUnionPayload for registers", .{}),
1806 .stack_argument_offset => |off| {1818 .stack_argument_offset => |off| {
1807 return MCValue{ .stack_argument_offset = off - offset };1819 return MCValue{ .stack_argument_offset = off - payload_offset };
1808 },1820 },
1809 .stack_offset => |off| {1821 .stack_offset => |off| {
1810 return MCValue{ .stack_offset = off - offset };1822 return MCValue{ .stack_offset = off - payload_offset };
1811 },1823 },
1812 .memory => |addr| {1824 .memory => |addr| {
1813 return MCValue{ .memory = addr - offset };1825 return MCValue{ .memory = addr + payload_offset };
1814 },1826 },
1815 else => unreachable, // invalid MCValue for an error union1827 else => unreachable, // invalid MCValue for an error union
1816 }1828 }
...@@ -3478,6 +3490,9 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3478,6 +3490,9 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
34783490
3479 switch (self.ret_mcv) {3491 switch (self.ret_mcv) {
3480 .none => {},3492 .none => {},
3493 .immediate => {
3494 assert(ret_ty.isError());
3495 },
3481 .register => |reg| {3496 .register => |reg| {
3482 // Return result by value3497 // Return result by value
3483 try self.genSetReg(ret_ty, reg, operand);3498 try self.genSetReg(ret_ty, reg, operand);
...@@ -3867,7 +3882,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {...@@ -3867,7 +3882,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue {
3867 const error_type = ty.errorUnionSet();3882 const error_type = ty.errorUnionSet();
3868 const error_int_type = Type.initTag(.u16);3883 const error_int_type = Type.initTag(.u16);
38693884
3870 if (!error_type.hasRuntimeBits()) {3885 if (error_type.errorSetCardinality() == .zero) {
3871 return MCValue{ .immediate = 0 }; // always false3886 return MCValue{ .immediate = 0 }; // always false
3872 }3887 }
38733888
...@@ -4975,7 +4990,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -4975,7 +4990,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
4975 const ref_int = @enumToInt(inst);4990 const ref_int = @enumToInt(inst);
4976 if (ref_int < Air.Inst.Ref.typed_value_map.len) {4991 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
4977 const tv = Air.Inst.Ref.typed_value_map[ref_int];4992 const tv = Air.Inst.Ref.typed_value_map[ref_int];
4978 if (!tv.ty.hasRuntimeBits()) {4993 if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) {
4979 return MCValue{ .none = {} };4994 return MCValue{ .none = {} };
4980 }4995 }
4981 return self.genTypedValue(tv);4996 return self.genTypedValue(tv);
...@@ -4983,7 +4998,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -4983,7 +4998,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
49834998
4984 // If the type has no codegen bits, no need to store it.4999 // If the type has no codegen bits, no need to store it.
4985 const inst_ty = self.air.typeOf(inst);5000 const inst_ty = self.air.typeOf(inst);
4986 if (!inst_ty.hasRuntimeBits())5001 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())
4987 return MCValue{ .none = {} };5002 return MCValue{ .none = {} };
49885003
4989 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);5004 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 {...@@ -5147,26 +5162,35 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
5147 }5162 }
5148 },5163 },
5149 .ErrorSet => {5164 .ErrorSet => {
5150 const err_name = typed_value.val.castTag(.@"error").?.data.name;5165 switch (typed_value.val.tag()) {
5151 const module = self.bin_file.options.module.?;5166 .@"error" => {
5152 const global_error_set = module.global_error_set;5167 const err_name = typed_value.val.castTag(.@"error").?.data.name;
5153 const error_index = global_error_set.get(err_name).?;5168 const module = self.bin_file.options.module.?;
5154 return MCValue{ .immediate = error_index };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 }
5155 },5178 },
5156 .ErrorUnion => {5179 .ErrorUnion => {
5157 const error_type = typed_value.ty.errorUnionSet();5180 const error_type = typed_value.ty.errorUnionSet();
5158 const payload_type = typed_value.ty.errorUnionPayload();5181 const payload_type = typed_value.ty.errorUnionPayload();
51595182
5160 if (typed_value.val.castTag(.eu_payload)) |_| {5183 if (error_type.errorSetCardinality() == .zero) {
5161 if (!payload_type.hasRuntimeBits()) {5184 const payload_val = typed_value.val.castTag(.eu_payload).?.data;
5162 // We use the error type directly as the type.5185 return self.genTypedValue(.{ .ty = payload_type, .val = payload_val });
5163 return MCValue{ .immediate = 0 };5186 }
5164 }5187
5165 } else {5188 const is_pl = typed_value.val.errorUnionIsPayload();
5166 if (!payload_type.hasRuntimeBits()) {5189
5167 // We use the error type directly as the type.5190 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
5168 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });5191 // We use the error type directly as the type.
5169 }5192 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
5193 return self.genTypedValue(.{ .ty = error_type, .val = err_val });
5170 }5194 }
5171 },5195 },
51725196
...@@ -5231,7 +5255,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5231,7 +5255,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
52315255
5232 if (ret_ty.zigTypeTag() == .NoReturn) {5256 if (ret_ty.zigTypeTag() == .NoReturn) {
5233 result.return_value = .{ .unreach = {} };5257 result.return_value = .{ .unreach = {} };
5234 } else if (!ret_ty.hasRuntimeBits()) {5258 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime()) {
5235 result.return_value = .{ .none = {} };5259 result.return_value = .{ .none = {} };
5236 } else {5260 } else {
5237 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));5261 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
...@@ -5278,11 +5302,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -5278,11 +5302,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
5278 .Unspecified => {5302 .Unspecified => {
5279 if (ret_ty.zigTypeTag() == .NoReturn) {5303 if (ret_ty.zigTypeTag() == .NoReturn) {
5280 result.return_value = .{ .unreach = {} };5304 result.return_value = .{ .unreach = {} };
5281 } else if (!ret_ty.hasRuntimeBits()) {5305 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
5282 result.return_value = .{ .none = {} };5306 result.return_value = .{ .none = {} };
5283 } else {5307 } else {
5284 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));5308 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) {
5286 result.return_value = .{ .register = .r0 };5313 result.return_value = .{ .register = .r0 };
5287 } else {5314 } else {
5288 // The result is returned by reference, not by5315 // 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" {...@@ -441,6 +441,7 @@ test "return function call to error set from error union function" {
441441
442test "optional error set is the same size as error set" {442test "optional error set is the same size as error set" {
443 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO443 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
444 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
444445
445 comptime try expect(@sizeOf(?anyerror) == @sizeOf(anyerror));446 comptime try expect(@sizeOf(?anyerror) == @sizeOf(anyerror));
446 comptime try expect(@alignOf(?anyerror) == @alignOf(anyerror));447 comptime try expect(@alignOf(?anyerror) == @alignOf(anyerror));