| ... | ... | @@ -809,10 +809,9 @@ fn allocMem(self: *Self, inst: Air.Inst.Index, abi_size: u32, abi_align: u32) !u |
| 809 | 809 | if (abi_align > self.stack_align) |
| 810 | 810 | self.stack_align = abi_align; |
| 811 | 811 | // TODO find a free slot instead of always appending |
| 812 | | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align); |
| 813 | | self.next_stack_offset = offset + abi_size; |
| 814 | | if (self.next_stack_offset > self.max_end_stack) |
| 815 | | self.max_end_stack = self.next_stack_offset; |
| 812 | const offset = mem.alignForwardGeneric(u32, self.next_stack_offset, abi_align) + abi_size; |
| 813 | self.next_stack_offset = offset; |
| 814 | self.max_end_stack = @maximum(self.max_end_stack, self.next_stack_offset); |
| 816 | 815 | try self.stack.putNoClobber(self.gpa, offset, .{ |
| 817 | 816 | .inst = inst, |
| 818 | 817 | .size = abi_size, |
| ... | ... | @@ -825,9 +824,10 @@ fn allocMemPtr(self: *Self, inst: Air.Inst.Index) !u32 { |
| 825 | 824 | const elem_ty = self.air.typeOfIndex(inst).elemType(); |
| 826 | 825 | |
| 827 | 826 | if (!elem_ty.hasRuntimeBits()) { |
| 828 | | // As this stack item will never be dereferenced at runtime, |
| 829 | | // return the current stack offset |
| 830 | | return self.next_stack_offset; |
| 827 | // return the stack offset 0. Stack offset 0 will be where all |
| 828 | // zero-sized stack allocations live as non-zero-sized |
| 829 | // allocations will always have an offset > 0. |
| 830 | return @as(u32, 0); |
| 831 | 831 | } |
| 832 | 832 | |
| 833 | 833 | const target = self.target.*; |
| ... | ... | @@ -1097,8 +1097,8 @@ fn airSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 1097 | 1097 | const ptr_bytes = @divExact(ptr_bits, 8); |
| 1098 | 1098 | |
| 1099 | 1099 | const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2); |
| 1100 | | try self.genSetStack(ptr_ty, stack_offset + ptr_bytes, ptr); |
| 1101 | | try self.genSetStack(len_ty, stack_offset, len); |
| 1100 | try self.genSetStack(ptr_ty, stack_offset, ptr); |
| 1101 | try self.genSetStack(len_ty, stack_offset - ptr_bytes, len); |
| 1102 | 1102 | break :result MCValue{ .stack_offset = stack_offset }; |
| 1103 | 1103 | }; |
| 1104 | 1104 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | ... | @@ -1515,7 +1515,13 @@ fn binOp( |
| 1515 | 1515 | const elem_size = elem_ty.abiSize(self.target.*); |
| 1516 | 1516 | |
| 1517 | 1517 | if (elem_size == 1) { |
| 1518 | | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1518 | const base_tag: Air.Inst.Tag = switch (tag) { |
| 1519 | .ptr_add => .add, |
| 1520 | .ptr_sub => .sub, |
| 1521 | else => unreachable, |
| 1522 | }; |
| 1523 | |
| 1524 | return try self.binOpRegister(base_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1519 | 1525 | } else { |
| 1520 | 1526 | // convert the offset into a byte offset by |
| 1521 | 1527 | // multiplying it with elem_size |
| ... | ... | @@ -1724,14 +1730,12 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void { |
| 1724 | 1730 | fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1725 | 1731 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1726 | 1732 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1727 | | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 1728 | | const ptr_bytes = @divExact(ptr_bits, 8); |
| 1729 | 1733 | const mcv = try self.resolveInst(ty_op.operand); |
| 1730 | 1734 | switch (mcv) { |
| 1731 | 1735 | .dead, .unreach, .none => unreachable, |
| 1732 | 1736 | .register => unreachable, // a slice doesn't fit in one register |
| 1733 | 1737 | .stack_offset => |off| { |
| 1734 | | break :result MCValue{ .stack_offset = off + ptr_bytes }; |
| 1738 | break :result MCValue{ .stack_offset = off }; |
| 1735 | 1739 | }, |
| 1736 | 1740 | .memory => |addr| { |
| 1737 | 1741 | break :result MCValue{ .memory = addr }; |
| ... | ... | @@ -1752,7 +1756,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1752 | 1756 | .dead, .unreach, .none => unreachable, |
| 1753 | 1757 | .register => unreachable, // a slice doesn't fit in one register |
| 1754 | 1758 | .stack_offset => |off| { |
| 1755 | | break :result MCValue{ .stack_offset = off }; |
| 1759 | break :result MCValue{ .stack_offset = off - ptr_bytes }; |
| 1756 | 1760 | }, |
| 1757 | 1761 | .memory => |addr| { |
| 1758 | 1762 | break :result MCValue{ .memory = addr + ptr_bytes }; |
| ... | ... | @@ -1772,7 +1776,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1772 | 1776 | switch (mcv) { |
| 1773 | 1777 | .dead, .unreach, .none => unreachable, |
| 1774 | 1778 | .ptr_stack_offset => |off| { |
| 1775 | | break :result MCValue{ .ptr_stack_offset = off + ptr_bytes }; |
| 1779 | break :result MCValue{ .ptr_stack_offset = off - ptr_bytes }; |
| 1776 | 1780 | }, |
| 1777 | 1781 | else => return self.fail("TODO implement ptr_slice_len_ptr for {}", .{mcv}), |
| 1778 | 1782 | } |
| ... | ... | @@ -1819,7 +1823,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1819 | 1823 | defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register}); |
| 1820 | 1824 | |
| 1821 | 1825 | const base_mcv: MCValue = switch (slice_mcv) { |
| 1822 | | .stack_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_offset = off + 8 }) }, |
| 1826 | .stack_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_offset = off }) }, |
| 1823 | 1827 | else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}), |
| 1824 | 1828 | }; |
| 1825 | 1829 | self.register_manager.freezeRegs(&.{base_mcv.register}); |
| ... | ... | @@ -2293,13 +2297,10 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 2293 | 2297 | const mcv = try self.resolveInst(operand); |
| 2294 | 2298 | const ptr_ty = self.air.typeOf(operand); |
| 2295 | 2299 | const struct_ty = ptr_ty.childType(); |
| 2296 | | const struct_size = @intCast(u32, struct_ty.abiSize(self.target.*)); |
| 2297 | 2300 | const struct_field_offset = @intCast(u32, struct_ty.structFieldOffset(index, self.target.*)); |
| 2298 | | const struct_field_ty = struct_ty.structFieldType(index); |
| 2299 | | const struct_field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); |
| 2300 | 2301 | switch (mcv) { |
| 2301 | 2302 | .ptr_stack_offset => |off| { |
| 2302 | | break :result MCValue{ .ptr_stack_offset = off + struct_size - struct_field_offset - struct_field_size }; |
| 2303 | break :result MCValue{ .ptr_stack_offset = off - struct_field_offset }; |
| 2303 | 2304 | }, |
| 2304 | 2305 | else => { |
| 2305 | 2306 | const offset_reg = try self.copyToTmpRegister(ptr_ty, .{ |
| ... | ... | @@ -2621,11 +2622,15 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2621 | 2622 | .Pointer => Type.usize, |
| 2622 | 2623 | .ErrorSet => Type.initTag(.u16), |
| 2623 | 2624 | .Optional => blk: { |
| 2624 | | if (lhs_ty.isPtrLikeOptional()) { |
| 2625 | var opt_buffer: Type.Payload.ElemType = undefined; |
| 2626 | const payload_ty = lhs_ty.optionalChild(&opt_buffer); |
| 2627 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| 2628 | break :blk Type.initTag(.u1); |
| 2629 | } else if (lhs_ty.isPtrLikeOptional()) { |
| 2625 | 2630 | break :blk Type.usize; |
| 2631 | } else { |
| 2632 | return self.fail("TODO AArch64 cmp non-pointer optionals", .{}); |
| 2626 | 2633 | } |
| 2627 | | |
| 2628 | | return self.fail("TODO AArch64 cmp optionals", .{}); |
| 2629 | 2634 | }, |
| 2630 | 2635 | .Float => return self.fail("TODO AArch64 cmp floats", .{}), |
| 2631 | 2636 | else => unreachable, |
| ... | ... | @@ -3318,8 +3323,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3318 | 3323 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 3319 | 3324 | }, |
| 3320 | 3325 | .register => |reg| { |
| 3321 | | const adj_off = stack_offset + abi_size; |
| 3322 | | |
| 3323 | 3326 | switch (abi_size) { |
| 3324 | 3327 | 1, 2, 4, 8 => { |
| 3325 | 3328 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| ... | ... | @@ -3334,7 +3337,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 3334 | 3337 | .tag = tag, |
| 3335 | 3338 | .data = .{ .load_store_stack = .{ |
| 3336 | 3339 | .rt = rt, |
| 3337 | | .offset = @intCast(u32, adj_off), |
| 3340 | .offset = @intCast(u32, stack_offset), |
| 3338 | 3341 | } }, |
| 3339 | 3342 | }); |
| 3340 | 3343 | }, |
| ... | ... | @@ -3430,13 +3433,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3430 | 3433 | else => unreachable, // unexpected register size |
| 3431 | 3434 | } |
| 3432 | 3435 | }, |
| 3433 | | .ptr_stack_offset => |unadjusted_off| { |
| 3436 | .ptr_stack_offset => |off| { |
| 3434 | 3437 | // TODO: maybe addressing from sp instead of fp |
| 3435 | | const elem_ty = ty.childType(); |
| 3436 | | const abi_size = elem_ty.abiSize(self.target.*); |
| 3437 | | const adj_off = unadjusted_off + abi_size; |
| 3438 | | |
| 3439 | | const imm12 = math.cast(u12, adj_off) catch |
| 3438 | const imm12 = math.cast(u12, off) catch |
| 3440 | 3439 | return self.fail("TODO larger stack offsets", .{}); |
| 3441 | 3440 | |
| 3442 | 3441 | _ = try self.addInst(.{ |
| ... | ... | @@ -3526,9 +3525,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3526 | 3525 | try self.genSetReg(ty, reg, .{ .immediate = addr }); |
| 3527 | 3526 | try self.genLdrRegister(reg, reg, ty.abiSize(self.target.*)); |
| 3528 | 3527 | }, |
| 3529 | | .stack_offset => |unadjusted_off| { |
| 3528 | .stack_offset => |off| { |
| 3530 | 3529 | const abi_size = ty.abiSize(self.target.*); |
| 3531 | | const adj_off = unadjusted_off + abi_size; |
| 3532 | 3530 | |
| 3533 | 3531 | switch (abi_size) { |
| 3534 | 3532 | 1, 2, 4, 8 => { |
| ... | ... | @@ -3548,7 +3546,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3548 | 3546 | .tag = tag, |
| 3549 | 3547 | .data = .{ .load_store_stack = .{ |
| 3550 | 3548 | .rt = rt, |
| 3551 | | .offset = @intCast(u32, adj_off), |
| 3549 | .offset = @intCast(u32, off), |
| 3552 | 3550 | } }, |
| 3553 | 3551 | }); |
| 3554 | 3552 | }, |
| ... | ... | @@ -3583,8 +3581,8 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 3583 | 3581 | const ptr_bytes = @divExact(ptr_bits, 8); |
| 3584 | 3582 | |
| 3585 | 3583 | const stack_offset = try self.allocMem(inst, ptr_bytes * 2, ptr_bytes * 2); |
| 3586 | | try self.genSetStack(ptr_ty, stack_offset + ptr_bytes, ptr); |
| 3587 | | try self.genSetStack(Type.initTag(.usize), stack_offset, .{ .immediate = array_len }); |
| 3584 | try self.genSetStack(ptr_ty, stack_offset, ptr); |
| 3585 | try self.genSetStack(Type.initTag(.usize), stack_offset - ptr_bytes, .{ .immediate = array_len }); |
| 3588 | 3586 | break :result MCValue{ .stack_offset = stack_offset }; |
| 3589 | 3587 | }; |
| 3590 | 3588 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |