authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-05 21:22:09+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-14 22:09:43+01:00
logf598d2ae056e72bda1efb3bc7d77e8183e95e191
tree7ce813c5bc72a96ccc507285ce0c4d6edd432a5d
parent8204ad193788f55b7fb5c5a2dd9a1902d964ed70
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: implement unwrap_errunion_err and struct_field_ptr


1 files changed, 60 insertions(+), 18 deletions(-)

src/arch/aarch64/CodeGen.zig+60-18
...@@ -1098,7 +1098,14 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {...@@ -1098,7 +1098,14 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
10981098
1099fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {1099fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
1100 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1100 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1101 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement unwrap error union error for {}", .{self.target.cpu.arch});1101 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1102 const error_union_ty = self.air.typeOf(ty_op.operand);
1103 const payload_ty = error_union_ty.errorUnionPayload();
1104 const mcv = try self.resolveInst(ty_op.operand);
1105 if (!payload_ty.hasRuntimeBits()) break :result mcv;
1106
1107 return self.fail("TODO implement unwrap error union error for non-empty payloads", .{});
1108 };
1102 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1109 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1103}1110}
11041111
...@@ -1644,20 +1651,31 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void {...@@ -1644,20 +1651,31 @@ fn airStore(self: *Self, inst: Air.Inst.Index) !void {
1644fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {1651fn airStructFieldPtr(self: *Self, inst: Air.Inst.Index) !void {
1645 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;1652 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1646 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;1653 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
1647 return self.structFieldPtr(extra.struct_operand, ty_pl.ty, extra.field_index);1654 const result = try self.structFieldPtr(inst, extra.struct_operand, extra.field_index);
1655 return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none });
1648}1656}
16491657
1650fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {1658fn airStructFieldPtrIndex(self: *Self, inst: Air.Inst.Index, index: u8) !void {
1651 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1659 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1652 return self.structFieldPtr(ty_op.operand, ty_op.ty, index);1660 const result = try self.structFieldPtr(inst, ty_op.operand, index);
1661 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1653}1662}
1654fn structFieldPtr(self: *Self, operand: Air.Inst.Ref, ty: Air.Inst.Ref, index: u32) !void {1663
1655 _ = self;1664fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, index: u32) !MCValue {
1656 _ = operand;1665 return if (self.liveness.isUnused(inst)) .dead else result: {
1657 _ = ty;1666 const mcv = try self.resolveInst(operand);
1658 _ = index;1667 const struct_ty = self.air.typeOf(operand).childType();
1659 return self.fail("TODO implement codegen struct_field_ptr", .{});1668 const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*));
1660 //return self.finishAir(inst, result, .{ extra.struct_ptr, .none, .none });1669 const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*));
1670 const struct_field_ty = struct_ty.structFieldType(index);
1671 const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*));
1672 switch (mcv) {
1673 .ptr_stack_offset => |off| {
1674 break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size };
1675 },
1676 else => return self.fail("TODO implement codegen struct_field_ptr for {}", .{mcv}),
1677 }
1678 };
1661}1679}
16621680
1663fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {1681fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
...@@ -1754,10 +1772,16 @@ fn airFence(self: *Self) !void {...@@ -1754,10 +1772,16 @@ fn airFence(self: *Self) !void {
17541772
1755fn airCall(self: *Self, inst: Air.Inst.Index) !void {1773fn airCall(self: *Self, inst: Air.Inst.Index) !void {
1756 const pl_op = self.air.instructions.items(.data)[inst].pl_op;1774 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
1757 const fn_ty = self.air.typeOf(pl_op.operand);
1758 const callee = pl_op.operand;1775 const callee = pl_op.operand;
1759 const extra = self.air.extraData(Air.Call, pl_op.payload);1776 const extra = self.air.extraData(Air.Call, pl_op.payload);
1760 const args = @bitCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);1777 const args = @bitCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
1778 const ty = self.air.typeOf(callee);
1779
1780 const fn_ty = switch (ty.zigTypeTag()) {
1781 .Fn => ty,
1782 .Pointer => ty.childType(),
1783 else => unreachable,
1784 };
17611785
1762 var info = try self.resolveCallingConventionValues(fn_ty);1786 var info = try self.resolveCallingConventionValues(fn_ty);
1763 defer info.deinit(self);1787 defer info.deinit(self);
...@@ -1821,7 +1845,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -1821,7 +1845,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
1821 return self.fail("TODO implement calling bitcasted functions", .{});1845 return self.fail("TODO implement calling bitcasted functions", .{});
1822 }1846 }
1823 } else {1847 } else {
1824 return self.fail("TODO implement calling runtime known function pointer", .{});1848 assert(ty.zigTypeTag() == .Pointer);
1849 const mcv = try self.resolveInst(callee);
1850 try self.genSetReg(Type.initTag(.usize), .x30, mcv);
1851
1852 _ = try self.addInst(.{
1853 .tag = .blr,
1854 .data = .{ .reg = .x30 },
1855 });
1825 }1856 }
1826 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {1857 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
1827 for (info.args) |mc_arg, arg_i| {1858 for (info.args) |mc_arg, arg_i| {
...@@ -2008,12 +2039,23 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -2008,12 +2039,23 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
20082039
2009fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {2040fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
2010 const bin_op = self.air.instructions.items(.data)[inst].bin_op;2041 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
2042
2011 if (self.liveness.isUnused(inst))2043 if (self.liveness.isUnused(inst))
2012 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });2044 return self.finishAir(inst, .dead, .{ bin_op.lhs, bin_op.rhs, .none });
2045
2013 const ty = self.air.typeOf(bin_op.lhs);2046 const ty = self.air.typeOf(bin_op.lhs);
2014 assert(ty.eql(self.air.typeOf(bin_op.rhs)));2047
2015 if (ty.zigTypeTag() == .ErrorSet)2048 if (ty.abiSize(self.target.*) > 8) {
2016 return self.fail("TODO implement cmp for errors", .{});2049 return self.fail("TODO cmp for types with size > 8", .{});
2050 }
2051
2052 const signedness: std.builtin.Signedness = blk: {
2053 // by default we tell the operand type is unsigned (i.e. bools and enum values)
2054 if (ty.zigTypeTag() != .Int) break :blk .unsigned;
2055
2056 // incase of an actual integer, we emit the correct signedness
2057 break :blk ty.intInfo(self.target.*).signedness;
2058 };
20172059
2018 const lhs = try self.resolveInst(bin_op.lhs);2060 const lhs = try self.resolveInst(bin_op.lhs);
2019 const rhs = try self.resolveInst(bin_op.rhs);2061 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -2089,9 +2131,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -2089,9 +2131,9 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
2089 else => unreachable,2131 else => unreachable,
2090 }2132 }
20912133
2092 break :result switch (ty.isSignedInt()) {2134 break :result switch (signedness) {
2093 true => MCValue{ .compare_flags_signed = op },2135 .signed => MCValue{ .compare_flags_signed = op },
2094 false => MCValue{ .compare_flags_unsigned = op },2136 .unsigned => MCValue{ .compare_flags_unsigned = op },
2095 };2137 };
2096 };2138 };
2097 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });2139 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });