| ... | ... | @@ -1348,7 +1348,7 @@ fn slicePtr(self: *Self, mcv: MCValue) !MCValue { |
| 1348 | 1348 | .dead, .unreach => unreachable, |
| 1349 | 1349 | .register => unreachable, // a slice doesn't fit in one register |
| 1350 | 1350 | .stack_argument_offset => |off| { |
| 1351 | | return MCValue{ .stack_argument_offset = off + 4 }; |
| 1351 | return MCValue{ .stack_argument_offset = off }; |
| 1352 | 1352 | }, |
| 1353 | 1353 | .stack_offset => |off| { |
| 1354 | 1354 | return MCValue{ .stack_offset = off }; |
| ... | ... | @@ -1377,7 +1377,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1377 | 1377 | .dead, .unreach => unreachable, |
| 1378 | 1378 | .register => unreachable, // a slice doesn't fit in one register |
| 1379 | 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 | 1382 | .stack_offset => |off| { |
| 1383 | 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 | 1782 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 1783 | 1783 | }, |
| 1784 | 1784 | .memory => |addr| try self.genSetReg(Type.usize, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 1785 | | .stack_argument_offset => |unadjusted_off| { |
| 1786 | | const adj_off = unadjusted_off + elem_size; |
| 1787 | | |
| 1785 | .stack_argument_offset => |off| { |
| 1788 | 1786 | _ = try self.addInst(.{ |
| 1789 | 1787 | .tag = .ldr_ptr_stack_argument, |
| 1790 | 1788 | .data = .{ .r_stack_offset = .{ |
| 1791 | 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 | 1882 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1885 | 1883 | const mcv = try self.resolveInst(operand); |
| 1886 | 1884 | const struct_ty = self.air.typeOf(operand); |
| 1887 | | const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); |
| 1888 | 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 | 1887 | switch (mcv) { |
| 1894 | 1888 | .dead, .unreach => unreachable, |
| 1895 | 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 | 1892 | .stack_offset => |off| { |
| 1899 | 1893 | break :result MCValue{ .stack_offset = off - struct_field_offset }; |
| 1900 | 1894 | }, |
| 1901 | 1895 | .memory => |addr| { |
| 1902 | | break :result MCValue{ .memory = addr + adjusted_field_offset }; |
| 1896 | break :result MCValue{ .memory = addr + struct_field_offset }; |
| 1903 | 1897 | }, |
| 1904 | 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 | 3677 | try self.genSetReg(ptr_ty, src_reg, .{ .ptr_stack_offset = off }); |
| 3684 | 3678 | }, |
| 3685 | 3679 | .memory => |addr| try self.genSetReg(ptr_ty, src_reg, .{ .immediate = @intCast(u32, addr) }), |
| 3686 | | .stack_argument_offset => |unadjusted_off| { |
| 3687 | | const adj_off = unadjusted_off + abi_size; |
| 3688 | | |
| 3680 | .stack_argument_offset => |off| { |
| 3689 | 3681 | _ = try self.addInst(.{ |
| 3690 | 3682 | .tag = .ldr_ptr_stack_argument, |
| 3691 | 3683 | .data = .{ .r_stack_offset = .{ |
| 3692 | 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 | 3940 | }); |
| 3949 | 3941 | } |
| 3950 | 3942 | }, |
| 3951 | | .stack_argument_offset => |unadjusted_off| { |
| 3943 | .stack_argument_offset => |off| { |
| 3952 | 3944 | const abi_size = ty.abiSize(self.target.*); |
| 3953 | | const adj_off = unadjusted_off + abi_size; |
| 3954 | 3945 | |
| 3955 | 3946 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3956 | 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 | 3954 | .tag = tag, |
| 3964 | 3955 | .data = .{ .r_stack_offset = .{ |
| 3965 | 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 | 3970 | if (!self.wantSafety()) |
| 3980 | 3971 | return; // The already existing value will do just fine. |
| 3981 | 3972 | // TODO Upgrade this to a memset call when we have that available. |
| 3982 | | switch (ty.abiSize(self.target.*)) { |
| 3973 | switch (abi_size) { |
| 3983 | 3974 | 1 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaa }), |
| 3984 | 3975 | 2 => return self.genSetStackArgument(ty, stack_offset, .{ .immediate = 0xaaaa }), |
| 3985 | 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 | 3978 | } |
| 3988 | 3979 | }, |
| 3989 | 3980 | .register => |reg| { |
| 3990 | | const adj_off = stack_offset - abi_size; |
| 3991 | | |
| 3992 | 3981 | switch (abi_size) { |
| 3993 | 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 | 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 | 3987 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 3999 | 3988 | 1 => .strb, |
| ... | ... | @@ -4011,9 +4000,9 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4011 | 4000 | }); |
| 4012 | 4001 | }, |
| 4013 | 4002 | 2 => { |
| 4014 | | const offset = if (adj_off <= math.maxInt(u8)) blk: { |
| 4015 | | break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, adj_off)); |
| 4016 | | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = adj_off })); |
| 4003 | const offset = if (stack_offset <= math.maxInt(u8)) blk: { |
| 4004 | break :blk Instruction.ExtraLoadStoreOffset.imm(@intCast(u8, stack_offset)); |
| 4005 | } else Instruction.ExtraLoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u32), MCValue{ .immediate = stack_offset })); |
| 4017 | 4006 | |
| 4018 | 4007 | _ = try self.addInst(.{ |
| 4019 | 4008 | .tag = .strh, |
| ... | ... | @@ -4060,8 +4049,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4060 | 4049 | } |
| 4061 | 4050 | |
| 4062 | 4051 | // add dst_reg, sp, #stack_offset |
| 4063 | | const adj_dst_offset = stack_offset - abi_size; |
| 4064 | | const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(adj_dst_offset)) |x| x else { |
| 4052 | const dst_offset_op: Instruction.Operand = if (Instruction.Operand.fromU32(stack_offset)) |x| x else { |
| 4065 | 4053 | return self.fail("TODO load: set reg to stack offset with all possible offsets", .{}); |
| 4066 | 4054 | }; |
| 4067 | 4055 | _ = try self.addInst(.{ |
| ... | ... | @@ -4553,8 +4541,8 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 4553 | 4541 | if (ty.abiAlignment(self.target.*) == 8) |
| 4554 | 4542 | nsaa = std.mem.alignForwardGeneric(u32, nsaa, 8); |
| 4555 | 4543 | |
| 4556 | | result.args[i] = .{ .stack_argument_offset = nsaa }; |
| 4557 | 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 | 4571 | |
| 4584 | 4572 | for (param_types) |ty, i| { |
| 4585 | 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 | 4577 | result.args[i] = .{ .stack_argument_offset = stack_offset }; |
| 4588 | | stack_offset += @intCast(u32, ty.abiSize(self.target.*)); |
| 4589 | 4578 | } else { |
| 4590 | 4579 | result.args[i] = .{ .none = {} }; |
| 4591 | 4580 | } |