authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-23 23:07:12+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-05-24 15:34:52-07:00
log41f517e5f506500c4e3f0bea53d73db0a1daf456
treef0eb1bcce81e29e8aa732611c5acd7db5699a7e6
parentb42100c70fc306c6d6f69a55e9225a9a91e363ef

x64: update for new error union layout


2 files changed, 175 insertions(+), 78 deletions(-)

src/arch/x86_64/CodeGen.zig+171-77
...@@ -854,7 +854,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {...@@ -854,7 +854,7 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 {
854 const ptr_ty = self.air.typeOfIndex(inst);854 const ptr_ty = self.air.typeOfIndex(inst);
855 const elem_ty = ptr_ty.elemType();855 const elem_ty = ptr_ty.elemType();
856856
857 if (!elem_ty.hasRuntimeBits()) {857 if (!elem_ty.hasRuntimeBitsIgnoreComptime()) {
858 return self.allocMem(inst, @sizeOf(usize), @alignOf(usize));858 return self.allocMem(inst, @sizeOf(usize), @alignOf(usize));
859 }859 }
860860
...@@ -1786,21 +1786,34 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1786,21 +1786,34 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1786 const err_ty = err_union_ty.errorUnionSet();1786 const err_ty = err_union_ty.errorUnionSet();
1787 const payload_ty = err_union_ty.errorUnionPayload();1787 const payload_ty = err_union_ty.errorUnionPayload();
1788 const operand = try self.resolveInst(ty_op.operand);1788 const operand = try self.resolveInst(ty_op.operand);
1789 const operand_lock: ?RegisterLock = switch (operand) {
1790 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
1791 else => null,
1792 };
1793 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
17941789
1795 const result: MCValue = result: {1790 const result: MCValue = result: {
1796 if (!payload_ty.hasRuntimeBits()) break :result operand;1791 if (err_ty.errorSetCardinality() == .zero) {
1792 break :result MCValue{ .immediate = 0 };
1793 }
1794
1795 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1796 break :result operand;
1797 }
1798
1799 const err_off = errUnionErrOffset(err_union_ty, self.target.*);
1797 switch (operand) {1800 switch (operand) {
1798 .stack_offset => |off| {1801 .stack_offset => |off| {
1799 break :result MCValue{ .stack_offset = off };1802 const offset = off - @intCast(i32, err_off);
1803 break :result MCValue{ .stack_offset = offset };
1800 },1804 },
1801 .register => {1805 .register => |reg| {
1802 // TODO reuse operand1806 // TODO reuse operand
1803 break :result try self.copyToRegisterWithInstTracking(inst, err_ty, operand);1807 const lock = self.register_manager.lockRegAssumeUnused(reg);
1808 defer self.register_manager.unlockReg(lock);
1809 const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand);
1810 if (err_off > 0) {
1811 const shift = @intCast(u6, err_off * 8);
1812 try self.genShiftBinOpMir(.shr, err_union_ty, result.register, .{ .immediate = shift });
1813 } else {
1814 try self.truncateRegister(Type.anyerror, result.register);
1815 }
1816 break :result result;
1804 },1817 },
1805 else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),1818 else => return self.fail("TODO implement unwrap_err_err for {}", .{operand}),
1806 }1819 }
...@@ -1815,32 +1828,37 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -1815,32 +1828,37 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
1815 }1828 }
1816 const err_union_ty = self.air.typeOf(ty_op.operand);1829 const err_union_ty = self.air.typeOf(ty_op.operand);
1817 const payload_ty = err_union_ty.errorUnionPayload();1830 const payload_ty = err_union_ty.errorUnionPayload();
1831 const err_ty = err_union_ty.errorUnionSet();
1832 const operand = try self.resolveInst(ty_op.operand);
1833
1818 const result: MCValue = result: {1834 const result: MCValue = result: {
1819 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;1835 if (err_ty.errorSetCardinality() == .zero) {
1836 // TODO check if we can reuse
1837 break :result operand;
1838 }
18201839
1821 const operand = try self.resolveInst(ty_op.operand);1840 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1822 const operand_lock: ?RegisterLock = switch (operand) {1841 break :result MCValue.none;
1823 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),1842 }
1824 else => null,
1825 };
1826 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
18271843
1828 const abi_align = err_union_ty.abiAlignment(self.target.*);1844 const payload_off = errUnionPayloadOffset(err_union_ty, self.target.*);
1829 const err_ty = err_union_ty.errorUnionSet();
1830 const err_abi_size = mem.alignForwardGeneric(u32, @intCast(u32, err_ty.abiSize(self.target.*)), abi_align);
1831 switch (operand) {1845 switch (operand) {
1832 .stack_offset => |off| {1846 .stack_offset => |off| {
1833 const offset = off - @intCast(i32, err_abi_size);1847 const offset = off - @intCast(i32, payload_off);
1834 break :result MCValue{ .stack_offset = offset };1848 break :result MCValue{ .stack_offset = offset };
1835 },1849 },
1836 .register => {1850 .register => |reg| {
1837 // TODO reuse operand1851 // TODO reuse operand
1838 const shift = @intCast(u6, err_abi_size * @sizeOf(usize));1852 const lock = self.register_manager.lockRegAssumeUnused(reg);
1853 defer self.register_manager.unlockReg(lock);
1839 const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand);1854 const result = try self.copyToRegisterWithInstTracking(inst, err_union_ty, operand);
1840 try self.genShiftBinOpMir(.shr, Type.usize, result.register, .{ .immediate = shift });1855 if (payload_off > 0) {
1841 break :result MCValue{1856 const shift = @intCast(u6, payload_off * 8);
1842 .register = registerAlias(result.register, @intCast(u32, payload_ty.abiSize(self.target.*))),1857 try self.genShiftBinOpMir(.shr, err_union_ty, result.register, .{ .immediate = shift });
1843 };1858 } else {
1859 try self.truncateRegister(payload_ty, result.register);
1860 }
1861 break :result result;
1844 },1862 },
1845 else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}),1863 else => return self.fail("TODO implement unwrap_err_payload for {}", .{operand}),
1846 }1864 }
...@@ -1935,24 +1953,37 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -1935,24 +1953,37 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
1935/// T to E!T1953/// T to E!T
1936fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {1954fn airWrapErrUnionPayload(self: *Self, inst: Air.Inst.Index) !void {
1937 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1955 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1956
1938 if (self.liveness.isUnused(inst)) {1957 if (self.liveness.isUnused(inst)) {
1939 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });1958 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1940 }1959 }
1960
1941 const error_union_ty = self.air.getRefType(ty_op.ty);1961 const error_union_ty = self.air.getRefType(ty_op.ty);
1942 const error_ty = error_union_ty.errorUnionSet();1962 const error_ty = error_union_ty.errorUnionSet();
1943 const payload_ty = error_union_ty.errorUnionPayload();1963 const payload_ty = error_union_ty.errorUnionPayload();
1944 const operand = try self.resolveInst(ty_op.operand);1964 const operand = try self.resolveInst(ty_op.operand);
1945 assert(payload_ty.hasRuntimeBits());
19461965
1947 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));1966 const result: MCValue = result: {
1948 const abi_align = error_union_ty.abiAlignment(self.target.*);1967 if (error_ty.errorSetCardinality() == .zero) {
1949 const err_abi_size = @intCast(u32, error_ty.abiSize(self.target.*));1968 break :result operand;
1950 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));1969 }
1951 const offset = mem.alignForwardGeneric(u32, err_abi_size, abi_align);1970
1952 try self.genSetStack(error_ty, stack_offset, .{ .immediate = 0 }, .{});1971 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
1953 try self.genSetStack(payload_ty, stack_offset - @intCast(i32, offset), operand, .{});1972 break :result operand;
1973 }
1974
1975 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
1976 const abi_align = error_union_ty.abiAlignment(self.target.*);
1977 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));
1978 const payload_off = errUnionPayloadOffset(error_union_ty, self.target.*);
1979 const err_off = errUnionErrOffset(error_union_ty, self.target.*);
1980 try self.genSetStack(payload_ty, stack_offset - @intCast(i32, payload_off), operand, .{});
1981 try self.genSetStack(Type.anyerror, stack_offset - @intCast(i32, err_off), .{ .immediate = 0 }, .{});
1982
1983 break :result MCValue{ .stack_offset = stack_offset };
1984 };
19541985
1955 return self.finishAir(inst, .{ .stack_offset = stack_offset }, .{ ty_op.operand, .none, .none });1986 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1956}1987}
19571988
1958/// E to E!T1989/// E to E!T
...@@ -1962,19 +1993,22 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1962,19 +1993,22 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1962 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });1993 return self.finishAir(inst, .dead, .{ ty_op.operand, .none, .none });
1963 }1994 }
1964 const error_union_ty = self.air.getRefType(ty_op.ty);1995 const error_union_ty = self.air.getRefType(ty_op.ty);
1965 const error_ty = error_union_ty.errorUnionSet();
1966 const payload_ty = error_union_ty.errorUnionPayload();1996 const payload_ty = error_union_ty.errorUnionPayload();
1967 const err = try self.resolveInst(ty_op.operand);1997 const operand = try self.resolveInst(ty_op.operand);
1998
1968 const result: MCValue = result: {1999 const result: MCValue = result: {
1969 if (!payload_ty.hasRuntimeBits()) break :result err;2000 if (!payload_ty.hasRuntimeBitsIgnoreComptime()) {
2001 break :result operand;
2002 }
19702003
1971 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));2004 const abi_size = @intCast(u32, error_union_ty.abiSize(self.target.*));
1972 const abi_align = error_union_ty.abiAlignment(self.target.*);2005 const abi_align = error_union_ty.abiAlignment(self.target.*);
1973 const err_abi_size = @intCast(u32, error_ty.abiSize(self.target.*));
1974 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));2006 const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align));
1975 const offset = mem.alignForwardGeneric(u32, err_abi_size, abi_align);2007 const payload_off = errUnionPayloadOffset(error_union_ty, self.target.*);
1976 try self.genSetStack(error_ty, stack_offset, err, .{});2008 const err_off = errUnionErrOffset(error_union_ty, self.target.*);
1977 try self.genSetStack(payload_ty, stack_offset - @intCast(i32, offset), .undef, .{});2009 try self.genSetStack(Type.anyerror, stack_offset - @intCast(i32, err_off), operand, .{});
2010 try self.genSetStack(payload_ty, stack_offset - @intCast(i32, payload_off), .undef, .{});
2011
1978 break :result MCValue{ .stack_offset = stack_offset };2012 break :result MCValue{ .stack_offset = stack_offset };
1979 };2013 };
19802014
...@@ -2535,7 +2569,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -2535,7 +2569,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void {
2535 const ty_op = self.air.instructions.items(.data)[inst].ty_op;2569 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
2536 const elem_ty = self.air.typeOfIndex(inst);2570 const elem_ty = self.air.typeOfIndex(inst);
2537 const result: MCValue = result: {2571 const result: MCValue = result: {
2538 if (!elem_ty.hasRuntimeBits())2572 if (!elem_ty.hasRuntimeBitsIgnoreComptime())
2539 break :result MCValue.none;2573 break :result MCValue.none;
25402574
2541 const ptr = try self.resolveInst(ty_op.operand);2575 const ptr = try self.resolveInst(ty_op.operand);
...@@ -4102,6 +4136,9 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -4102,6 +4136,9 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
4102 const operand = try self.resolveInst(un_op);4136 const operand = try self.resolveInst(un_op);
4103 const ret_ty = self.fn_type.fnReturnType();4137 const ret_ty = self.fn_type.fnReturnType();
4104 switch (self.ret_mcv) {4138 switch (self.ret_mcv) {
4139 .immediate => {
4140 assert(ret_ty.isError());
4141 },
4105 .stack_offset => {4142 .stack_offset => {
4106 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);4143 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);
4107 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);4144 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
...@@ -4134,6 +4171,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -4134,6 +4171,9 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
4134 const ptr_ty = self.air.typeOf(un_op);4171 const ptr_ty = self.air.typeOf(un_op);
4135 const elem_ty = ptr_ty.elemType();4172 const elem_ty = ptr_ty.elemType();
4136 switch (self.ret_mcv) {4173 switch (self.ret_mcv) {
4174 .immediate => {
4175 assert(elem_ty.isError());
4176 },
4137 .stack_offset => {4177 .stack_offset => {
4138 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);4178 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);
4139 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);4179 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
...@@ -4603,7 +4643,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValu...@@ -4603,7 +4643,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValu
4603 const cmp_ty: Type = if (!ty.isPtrLikeOptional()) blk: {4643 const cmp_ty: Type = if (!ty.isPtrLikeOptional()) blk: {
4604 var buf: Type.Payload.ElemType = undefined;4644 var buf: Type.Payload.ElemType = undefined;
4605 const payload_ty = ty.optionalChild(&buf);4645 const payload_ty = ty.optionalChild(&buf);
4606 break :blk if (payload_ty.hasRuntimeBits()) Type.bool else ty;4646 break :blk if (payload_ty.hasRuntimeBitsIgnoreComptime()) Type.bool else ty;
4607 } else ty;4647 } else ty;
46084648
4609 try self.genBinOpMir(.cmp, cmp_ty, operand, MCValue{ .immediate = 0 });4649 try self.genBinOpMir(.cmp, cmp_ty, operand, MCValue{ .immediate = 0 });
...@@ -4619,25 +4659,36 @@ fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCV...@@ -4619,25 +4659,36 @@ fn isNonNull(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCV
46194659
4620fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {4660fn isErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
4621 const err_type = ty.errorUnionSet();4661 const err_type = ty.errorUnionSet();
4622 const payload_type = ty.errorUnionPayload();4662
4623 if (!err_type.hasRuntimeBits()) {4663 if (err_type.errorSetCardinality() == .zero) {
4624 return MCValue{ .immediate = 0 }; // always false4664 return MCValue{ .immediate = 0 }; // always false
4625 }4665 }
46264666
4627 try self.spillCompareFlagsIfOccupied();4667 try self.spillCompareFlagsIfOccupied();
4628 self.compare_flags_inst = inst;4668 self.compare_flags_inst = inst;
46294669
4630 if (!payload_type.hasRuntimeBits()) {4670 const err_off = errUnionErrOffset(ty, self.target.*);
4631 if (err_type.abiSize(self.target.*) <= 8) {4671 switch (operand) {
4632 try self.genBinOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });4672 .stack_offset => |off| {
4633 return MCValue{ .compare_flags_unsigned = .gt };4673 const offset = off - @intCast(i32, err_off);
4634 } else {4674 try self.genBinOpMir(.cmp, Type.anyerror, .{ .stack_offset = offset }, .{ .immediate = 0 });
4635 return self.fail("TODO isErr for errors with size larger than register size", .{});4675 },
4636 }4676 .register => |reg| {
4637 } else {4677 const maybe_lock = self.register_manager.lockReg(reg);
4638 try self.genBinOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 });4678 defer if (maybe_lock) |lock| self.register_manager.unlockReg(lock);
4639 return MCValue{ .compare_flags_unsigned = .gt };4679 const tmp_reg = try self.copyToTmpRegister(ty, operand);
4680 if (err_off > 0) {
4681 const shift = @intCast(u6, err_off * 8);
4682 try self.genShiftBinOpMir(.shr, ty, tmp_reg, .{ .immediate = shift });
4683 } else {
4684 try self.truncateRegister(Type.anyerror, tmp_reg);
4685 }
4686 try self.genBinOpMir(.cmp, Type.anyerror, .{ .register = tmp_reg }, .{ .immediate = 0 });
4687 },
4688 else => return self.fail("TODO implement isErr for {}", .{operand}),
4640 }4689 }
4690
4691 return MCValue{ .compare_flags_unsigned = .gt };
4641}4692}
46424693
4643fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {4694fn isNonErr(self: *Self, inst: Air.Inst.Index, ty: Type, operand: MCValue) !MCValue {
...@@ -5460,6 +5511,21 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -5460,6 +5511,21 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
5460 .immediate => |x_big| {5511 .immediate => |x_big| {
5461 const base_reg = opts.dest_stack_base orelse .rbp;5512 const base_reg = opts.dest_stack_base orelse .rbp;
5462 switch (abi_size) {5513 switch (abi_size) {
5514 0 => {
5515 assert(ty.isError());
5516 const payload = try self.addExtra(Mir.ImmPair{
5517 .dest_off = @bitCast(u32, -stack_offset),
5518 .operand = @truncate(u32, x_big),
5519 });
5520 _ = try self.addInst(.{
5521 .tag = .mov_mem_imm,
5522 .ops = Mir.Inst.Ops.encode(.{
5523 .reg1 = base_reg,
5524 .flags = 0b00,
5525 }),
5526 .data = .{ .payload = payload },
5527 });
5528 },
5463 1, 2, 4 => {5529 1, 2, 4 => {
5464 const payload = try self.addExtra(Mir.ImmPair{5530 const payload = try self.addExtra(Mir.ImmPair{
5465 .dest_off = @bitCast(u32, -stack_offset),5531 .dest_off = @bitCast(u32, -stack_offset),
...@@ -6642,7 +6708,7 @@ pub fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -6642,7 +6708,7 @@ pub fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
6642 const ref_int = @enumToInt(inst);6708 const ref_int = @enumToInt(inst);
6643 if (ref_int < Air.Inst.Ref.typed_value_map.len) {6709 if (ref_int < Air.Inst.Ref.typed_value_map.len) {
6644 const tv = Air.Inst.Ref.typed_value_map[ref_int];6710 const tv = Air.Inst.Ref.typed_value_map[ref_int];
6645 if (!tv.ty.hasRuntimeBits()) {6711 if (!tv.ty.hasRuntimeBitsIgnoreComptime() and !tv.ty.isError()) {
6646 return MCValue{ .none = {} };6712 return MCValue{ .none = {} };
6647 }6713 }
6648 return self.genTypedValue(tv);6714 return self.genTypedValue(tv);
...@@ -6650,7 +6716,7 @@ pub fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {...@@ -6650,7 +6716,7 @@ pub fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
66506716
6651 // If the type has no codegen bits, no need to store it.6717 // If the type has no codegen bits, no need to store it.
6652 const inst_ty = self.air.typeOf(inst);6718 const inst_ty = self.air.typeOf(inst);
6653 if (!inst_ty.hasRuntimeBits())6719 if (!inst_ty.hasRuntimeBitsIgnoreComptime() and !inst_ty.isError())
6654 return MCValue{ .none = {} };6720 return MCValue{ .none = {} };
66556721
6656 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);6722 const inst_index = @intCast(Air.Inst.Index, ref_int - Air.Inst.Ref.typed_value_map.len);
...@@ -6779,6 +6845,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -6779,6 +6845,7 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
6779 const target = self.target.*;6845 const target = self.target.*;
67806846
6781 switch (typed_value.ty.zigTypeTag()) {6847 switch (typed_value.ty.zigTypeTag()) {
6848 .Void => return MCValue{ .none = {} },
6782 .Pointer => switch (typed_value.ty.ptrSize()) {6849 .Pointer => switch (typed_value.ty.ptrSize()) {
6783 .Slice => {},6850 .Slice => {},
6784 else => {6851 else => {
...@@ -6840,26 +6907,35 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -6840,26 +6907,35 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
6840 }6907 }
6841 },6908 },
6842 .ErrorSet => {6909 .ErrorSet => {
6843 const err_name = typed_value.val.castTag(.@"error").?.data.name;6910 switch (typed_value.val.tag()) {
6844 const module = self.bin_file.options.module.?;6911 .@"error" => {
6845 const global_error_set = module.global_error_set;6912 const err_name = typed_value.val.castTag(.@"error").?.data.name;
6846 const error_index = global_error_set.get(err_name).?;6913 const module = self.bin_file.options.module.?;
6847 return MCValue{ .immediate = error_index };6914 const global_error_set = module.global_error_set;
6915 const error_index = global_error_set.get(err_name).?;
6916 return MCValue{ .immediate = error_index };
6917 },
6918 else => {
6919 // In this case we are rendering an error union which has a 0 bits payload.
6920 return MCValue{ .immediate = 0 };
6921 },
6922 }
6848 },6923 },
6849 .ErrorUnion => {6924 .ErrorUnion => {
6850 const error_type = typed_value.ty.errorUnionSet();6925 const error_type = typed_value.ty.errorUnionSet();
6851 const payload_type = typed_value.ty.errorUnionPayload();6926 const payload_type = typed_value.ty.errorUnionPayload();
68526927
6853 if (typed_value.val.castTag(.eu_payload)) |_| {6928 if (error_type.errorSetCardinality() == .zero) {
6854 if (!payload_type.hasRuntimeBits()) {6929 const payload_val = typed_value.val.castTag(.eu_payload).?.data;
6855 // We use the error type directly as the type.6930 return self.genTypedValue(.{ .ty = payload_type, .val = payload_val });
6856 return MCValue{ .immediate = 0 };6931 }
6857 }6932
6858 } else {6933 const is_pl = typed_value.val.errorUnionIsPayload();
6859 if (!payload_type.hasRuntimeBits()) {6934
6860 // We use the error type directly as the type.6935 if (!payload_type.hasRuntimeBitsIgnoreComptime()) {
6861 return self.genTypedValue(.{ .ty = error_type, .val = typed_value.val });6936 // We use the error type directly as the type.
6862 }6937 const err_val = if (!is_pl) typed_value.val else Value.initTag(.zero);
6938 return self.genTypedValue(.{ .ty = error_type, .val = err_val });
6863 }6939 }
6864 },6940 },
68656941
...@@ -6867,7 +6943,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {...@@ -6867,7 +6943,6 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
6867 .ComptimeFloat => unreachable,6943 .ComptimeFloat => unreachable,
6868 .Type => unreachable,6944 .Type => unreachable,
6869 .EnumLiteral => unreachable,6945 .EnumLiteral => unreachable,
6870 .Void => unreachable,
6871 .NoReturn => unreachable,6946 .NoReturn => unreachable,
6872 .Undefined => unreachable,6947 .Undefined => unreachable,
6873 .Null => unreachable,6948 .Null => unreachable,
...@@ -6921,11 +6996,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {...@@ -6921,11 +6996,14 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues {
6921 // Return values6996 // Return values
6922 if (ret_ty.zigTypeTag() == .NoReturn) {6997 if (ret_ty.zigTypeTag() == .NoReturn) {
6923 result.return_value = .{ .unreach = {} };6998 result.return_value = .{ .unreach = {} };
6924 } else if (!ret_ty.hasRuntimeBits()) {6999 } else if (!ret_ty.hasRuntimeBitsIgnoreComptime() and !ret_ty.isError()) {
6925 result.return_value = .{ .none = {} };7000 result.return_value = .{ .none = {} };
6926 } else {7001 } else {
6927 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));7002 const ret_ty_size = @intCast(u32, ret_ty.abiSize(self.target.*));
6928 if (ret_ty_size <= 8) {7003 if (ret_ty_size == 0) {
7004 assert(ret_ty.isError());
7005 result.return_value = .{ .immediate = 0 };
7006 } else if (ret_ty_size <= 8) {
6929 const aliased_reg = registerAlias(c_abi_int_return_regs[0], ret_ty_size);7007 const aliased_reg = registerAlias(c_abi_int_return_regs[0], ret_ty_size);
6930 result.return_value = .{ .register = aliased_reg };7008 result.return_value = .{ .register = aliased_reg };
6931 } else {7009 } else {
...@@ -7105,3 +7183,19 @@ fn intrinsicsAllowed(target: Target, ty: Type) bool {...@@ -7105,3 +7183,19 @@ fn intrinsicsAllowed(target: Target, ty: Type) bool {
7105fn hasAvxSupport(target: Target) bool {7183fn hasAvxSupport(target: Target) bool {
7106 return Target.x86.featureSetHasAny(target.cpu.features, .{ .avx, .avx2 });7184 return Target.x86.featureSetHasAny(target.cpu.features, .{ .avx, .avx2 });
7107}7185}
7186
7187fn errUnionPayloadOffset(ty: Type, target: std.Target) u64 {
7188 const payload_ty = ty.errorUnionPayload();
7189 return if (Type.anyerror.abiAlignment(target) >= payload_ty.abiAlignment(target))
7190 Type.anyerror.abiSize(target)
7191 else
7192 0;
7193}
7194
7195fn errUnionErrOffset(ty: Type, target: std.Target) u64 {
7196 const payload_ty = ty.errorUnionPayload();
7197 return if (Type.anyerror.abiAlignment(target) >= payload_ty.abiAlignment(target))
7198 0
7199 else
7200 payload_ty.abiSize(target);
7201}
src/codegen.zig+4-1
...@@ -442,7 +442,10 @@ pub fn generateSymbol(...@@ -442,7 +442,10 @@ pub fn generateSymbol(
442 .Int => {442 .Int => {
443 const info = typed_value.ty.intInfo(target);443 const info = typed_value.ty.intInfo(target);
444 if (info.bits <= 8) {444 if (info.bits <= 8) {
445 const x = @intCast(u8, typed_value.val.toUnsignedInt(target));445 const x: u8 = switch (info.signedness) {
446 .unsigned => @intCast(u8, typed_value.val.toUnsignedInt(target)),
447 .signed => @bitCast(u8, @intCast(i8, typed_value.val.toSignedInt())),
448 };
446 try code.append(x);449 try code.append(x);
447 return Result{ .appended = {} };450 return Result{ .appended = {} };
448 }451 }