| ... | @@ -1348,7 +1348,7 @@ fn slicePtr(self: *Self, mcv: MCValue) !MCValue { | ... | @@ -1348,7 +1348,7 @@ fn slicePtr(self: *Self, mcv: MCValue) !MCValue { |
| 1348 | .dead, .unreach => unreachable, | 1348 | .dead, .unreach => unreachable, |
| 1349 | .register => unreachable, // a slice doesn't fit in one register | 1349 | .register => unreachable, // a slice doesn't fit in one register |
| 1350 | .stack_argument_offset => |off| { | 1350 | .stack_argument_offset => |off| { |
| 1351 | return MCValue{ .stack_argument_offset = off + 4 }; | 1351 | return MCValue{ .stack_argument_offset = off }; |
| 1352 | }, | 1352 | }, |
| 1353 | .stack_offset => |off| { | 1353 | .stack_offset => |off| { |
| 1354 | return MCValue{ .stack_offset = off }; | 1354 | return MCValue{ .stack_offset = off }; |
| ... | @@ -1377,7 +1377,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1377,7 +1377,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1377 | .dead, .unreach => unreachable, | 1377 | .dead, .unreach => unreachable, |
| 1378 | .register => unreachable, // a slice doesn't fit in one register | 1378 | .register => unreachable, // a slice doesn't fit in one register |
| 1379 | .stack_argument_offset => |off| { | 1379 | .stack_argument_offset => |off| { |
| 1380 | break :result MCValue{ .stack_argument_offset = off }; | 1380 | break :result MCValue{ .stack_argument_offset = off - 4 }; |
| 1381 | }, | 1381 | }, |
| 1382 | .stack_offset => |off| { | 1382 | .stack_offset => |off| { |
| 1383 | break :result MCValue{ .stack_offset = off - 4 }; | 1383 | break :result MCValue{ .stack_offset = off - 4 }; |
| ... | @@ -1782,14 +1782,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -1782,14 +1782,12 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 1782 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); | 1782 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 1783 | }, | 1783 | }, |
| 1784 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), | 1784 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 1785 | .stack_argument_offset => |unadjusted_off| { | 1785 | .stack_argument_offset => |off| { |
| 1786 | const adj_off = unadjusted_off + elem_size; | | |
| 1787 | | | |
| 1788 | _ = try self.addInst(.{ | 1786 | _ = try self.addInst(.{ |
| 1789 | .tag = .ldr_ptr_stack_argument, | 1787 | .tag = .ldr_ptr_stack_argument, |
| 1790 | .data = .{ .r_stack_offset = .{ | 1788 | .data = .{ .r_stack_offset = .{ |
| 1791 | .rt = src_reg, | 1789 | .rt = src_reg, |
| 1792 | .stack_offset = adj_off, | 1790 | .stack_offset = off, |
| 1793 | } }, | 1791 | } }, |
| 1794 | }); | 1792 | }); |
| 1795 | }, | 1793 | }, |
| ... | @@ -1884,22 +1882,18 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1884,22 +1882,18 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1884 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1882 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1885 | const mcv = try self.resolveInst(operand); | 1883 | const mcv = try self.resolveInst(operand); |
| 1886 | const struct_ty = self.air.typeOf(operand); | 1884 | const struct_ty = self.air.typeOf(operand); |
| 1887 | const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); | | |
| 1888 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); | 1885 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); |
| 1889 | const struct_field_ty = struct_ty.structFieldType(index); | | |
| 1890 | const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); | | |
| 1891 | const adjusted_field_offset = struct_size - struct_field_offset - struct_field_size; | | |
| 1892 | | 1886 | |
| 1893 | switch (mcv) { | 1887 | switch (mcv) { |
| 1894 | .dead, .unreach => unreachable, | 1888 | .dead, .unreach => unreachable, |
| 1895 | .stack_argument_offset => |off| { | 1889 | .stack_argument_offset => |off| { |
| 1896 | break :result MCValue{ .stack_argument_offset = off + adjusted_field_offset }; | 1890 | break :result MCValue{ .stack_argument_offset = off - struct_field_offset }; |
| 1897 | }, | 1891 | }, |
| 1898 | .stack_offset => |off| { | 1892 | .stack_offset => |off| { |
| 1899 | break :result MCValue{ .stack_offset = off - struct_field_offset }; | 1893 | break :result MCValue{ .stack_offset = off - struct_field_offset }; |
| 1900 | }, | 1894 | }, |
| 1901 | .memory => |addr| { | 1895 | .memory => |addr| { |
| 1902 | break :result MCValue{ .memory = addr + adjusted_field_offset }; | 1896 | break :result MCValue{ .memory = addr + struct_field_offset }; |
| 1903 | }, | 1897 | }, |
| 1904 | else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}), | 1898 | else => return self.fail("TODO implement codegen struct_field_val for {}", .{mcv}), |
| 1905 | } | 1899 | } |
| ... | @@ -3683,14 +3677,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -3683,14 +3677,12 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3683 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); | 3677 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 3684 | }, | 3678 | }, |
| 3685 | .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }), | 3679 | .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 3686 | .stack_argument_offset => |unadjusted_off| { | 3680 | .stack_argument_offset => |off| { |
| 3687 | const adj_off = unadjusted_off + abi_size; | | |
| 3688 | | | |
| 3689 | _ = try self.addInst(.{ | 3681 | _ = try self.addInst(.{ |
| 3690 | .tag = .ldr_ptr_stack_argument, | 3682 | .tag = .ldr_ptr_stack_argument, |
| 3691 | .data = .{ .r_stack_offset = .{ | 3683 | .data = .{ .r_stack_offset = .{ |
| 3692 | .rt = src_reg, | 3684 | .rt = src_reg, |
| 3693 | .stack_offset = adj_off, | 3685 | .stack_offset = off, |
| 3694 | } }, | 3686 | } }, |
| 3695 | }); | 3687 | }); |
| 3696 | }, | 3688 | }, |
| ... | @@ -3948,9 +3940,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -3948,9 +3940,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3948 | }); | 3940 | }); |
| 3949 | } | 3941 | } |
| 3950 | }, | 3942 | }, |
| 3951 | .stack_argument_offset => |unadjusted_off| { | 3943 | .stack_argument_offset => |off| { |
| 3952 | const abi_size = ty.abiSize(self.target.*); | 3944 | const abi_size = ty.abiSize(self.target.*); |
| 3953 | const adj_off = unadjusted_off + abi_size; | | |
| 3954 | | 3945 | |
| 3955 | const tag: Mir.Inst.Tag = switch (abi_size) { | 3946 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3956 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument, | 3947 | 1 => if (ty.isSignedInt()) Mir.Inst.Tag.ldrsb_stack_argument else .ldrb_stack_argument, |
| ... | @@ -3963,7 +3954,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -3963,7 +3954,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3963 | .tag = tag, | 3954 | .tag = tag, |
| 3964 | .data = .{ .r_stack_offset = .{ | 3955 | .data = .{ .r_stack_offset = .{ |
| 3965 | .rt = reg, | 3956 | .rt = reg, |
| 3966 | .stack_offset = @intCast(u32, adj_off), | 3957 | .stack_offset = off, |
| 3967 | } }, | 3958 | } }, |
| 3968 | }); | 3959 | }); |
| 3969 | }, | 3960 | }, |
| ... | @@ -3979,7 +3970,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -3979,7 +3970,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 3979 | if (!self.wantSafety()) | 3970 | if (!self.wantSafety()) |
| 3980 | return; // The already existing value will do just fine. | 3971 | return; // The already existing value will do just fine. |
| 3981 | // TODO Upgrade this to a memset call when we have that available. | 3972 | // TODO Upgrade this to a memset call when we have that available. |
| 3982 | switch (ty.abiSize(self.target.*)) { | 3973 | switch (abi_size) { |
| 3983 | 1 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }), | 3974 | 1 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }), |
| 3984 | 2 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }), | 3975 | 2 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }), |
| 3985 | 4 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), | 3976 | 4 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaaaaaa }), |
| ... | @@ -3987,13 +3978,11 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -3987,13 +3978,11 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 3987 | } | 3978 | } |
| 3988 | }, | 3979 | }, |
| 3989 | .register => |reg| { | 3980 | .register => |reg| { |
| 3990 | const adj_off = stack_offset - abi_size; | | |
| 3991 | | | |
| 3992 | switch (abi_size) { | 3981 | switch (abi_size) { |
| 3993 | 1, 4 => { | 3982 | 1, 4 => { |
| 3994 | const offset = if (math.cast(u12, adj_off)) |imm| blk: { | 3983 | const offset = if (math.cast(u12, stack_offset)) |imm| blk: { |
| 3995 | break :blk Instruction.Offset.imm(imm); | 3984 | break :blk Instruction.Offset.imm(imm); |
| 3996 | } else |_| Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off }), .none); | 3985 | } else |_| Instruction.Offset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = stack_offset }), .none); |
| 3997 | | 3986 | |
| 3998 | const tag: Mir.Inst.Tag = switch (abi_size) { | 3987 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3999 | 1 => .strb, | 3988 | 1 => .strb, |
| ... | @@ -4011,9 +4000,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -4011,9 +4000,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4011 | }); | 4000 | }); |
| 4012 | }, | 4001 | }, |
| 4013 | 2 => { | 4002 | 2 => { |
| 4014 | const offset = if (adj_off <= math.maxInt(u8)) blk: { | 4003 | const offset = if (stack_offset <= math.maxInt(u8)) blk: { |
| 4015 | break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, adj_off)); | 4004 | break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, stack_offset)); |
| 4016 | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off })); | 4005 | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = stack_offset })); |
| 4017 | | 4006 | |
| 4018 | _ = try self.addInst(.{ | 4007 | _ = try self.addInst(.{ |
| 4019 | .tag = .strh, | 4008 | .tag = .strh, |
| ... | @@ -4060,8 +4049,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -4060,8 +4049,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4060 | } | 4049 | } |
| 4061 | | 4050 | |
| 4062 | // add dst_reg, sp, #stack_offset | 4051 | // add dst_reg, sp, #stack_offset |
| 4063 | const adj_dst_offset = stack_offset - abi_size; | 4052 | const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(stack_offset)) |x| x else { |
| 4064 | const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else { | | |
| 4065 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); | 4053 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| 4066 | }; | 4054 | }; |
| 4067 | _ = try self.addInst(.{ | 4055 | _ = try self.addInst(.{ |
| ... | @@ -4553,8 +4541,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -4553,8 +4541,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 4553 | if (ty.abiAlignment(self.target.*) == 8) | 4541 | if (ty.abiAlignment(self.target.*) == 8) |
| 4554 | nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8); | 4542 | nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8); |
| 4555 | | 4543 | |
| 4556 | result.args[i] = .{ .stack_argument_offset = nsaa }; | | |
| 4557 | nsaa += param_size; | 4544 | nsaa += param_size; |
| | 4545 | result.args[i] = .{ .stack_argument_offset = nsaa }; |
| 4558 | } | 4546 | } |
| 4559 | } | 4547 | } |
| 4560 | | 4548 | |
| ... | @@ -4583,9 +4571,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -4583,9 +4571,10 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 4583 | | 4571 | |
| 4584 | for (param_types) |ty, i| { | 4572 | for (param_types) |ty, i| { |
| 4585 | if (ty.abiSize(self.target.*) > 0) { | 4573 | if (ty.abiSize(self.target.*) > 0) { |
| 4586 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*)); | 4574 | const param_size = @intCast(u32, ty.abiSize(self.target.*)); |
| | 4575 | |
| | 4576 | stack_offset = std.mem.alignForwardGeneric(u32, stack_offset, ty.abiAlignment(self.target.*)) + param_size; |
| 4587 | result.args[i] = .{ .stack_argument_offset = stack_offset }; | 4577 | result.args[i] = .{ .stack_argument_offset = stack_offset }; |
| 4588 | stack_offset += @intCast(u32, ty.abiSize(self.target.*)); | | |
| 4589 | } else { | 4578 | } else { |
| 4590 | result.args[i] = .{ .none = {} }; | 4579 | result.args[i] = .{ .none = {} }; |
| 4591 | } | 4580 | } |