| ... | @@ -1442,8 +1442,29 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1442,8 +1442,29 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1442 | } | 1442 | } |
| 1443 | | 1443 | |
| 1444 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | 1444 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| | 1445 | const mod = self.bin_file.comp.module.?; |
| 1445 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; | 1446 | const bin_op = self.air.instructions.items(.data)[@intFromEnum(inst)].bin_op; |
| 1446 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement array_elem_val for {}", .{self.target.cpu.arch}); | 1447 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| | 1448 | const array_ty = self.typeOf(bin_op.lhs); |
| | 1449 | const array_mcv = try self.resolveInst(bin_op.lhs); |
| | 1450 | |
| | 1451 | const index_mcv = try self.resolveInst(bin_op.rhs); |
| | 1452 | |
| | 1453 | const elem_ty = array_ty.childType(mod); |
| | 1454 | const elem_abi_size = elem_ty.abiSize(mod); |
| | 1455 | |
| | 1456 | switch (array_mcv) { |
| | 1457 | // all we need to do is calculate the offset that the elem exits at. |
| | 1458 | .stack_offset => |off| { |
| | 1459 | if (index_mcv == .immediate) { |
| | 1460 | const true_offset: u32 = @intCast(index_mcv.immediate * elem_abi_size); |
| | 1461 | break :result MCValue{ .stack_offset = off + true_offset }; |
| | 1462 | } |
| | 1463 | return self.fail("TODO: airArrayElemVal with runtime index", .{}); |
| | 1464 | }, |
| | 1465 | else => return self.fail("TODO: airArrayElemVal {s}", .{@tagName(array_mcv)}), |
| | 1466 | } |
| | 1467 | }; |
| 1447 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1468 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1448 | } | 1469 | } |
| 1449 | | 1470 | |
| ... | @@ -1639,17 +1660,10 @@ fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerErro | ... | @@ -1639,17 +1660,10 @@ fn load(self: *Self, dst_mcv: MCValue, src_ptr: MCValue, ptr_ty: Type) InnerErro |
| 1639 | .dead => unreachable, | 1660 | .dead => unreachable, |
| 1640 | .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }), | 1661 | .immediate => |imm| try self.setValue(elem_ty, dst_mcv, .{ .memory = imm }), |
| 1641 | .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }), | 1662 | .ptr_stack_offset => |off| try self.setValue(elem_ty, dst_mcv, .{ .stack_offset = off }), |
| 1642 | .register => try self.setValue(elem_ty, dst_mcv, src_ptr), | | |
| 1643 | .memory, | | |
| 1644 | .stack_offset, | 1663 | .stack_offset, |
| 1645 | => { | 1664 | .register, |
| 1646 | const reg = try self.register_manager.allocReg(null, gp); | 1665 | => try self.setValue(elem_ty, dst_mcv, src_ptr), |
| 1647 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); | 1666 | .memory => return self.fail("TODO: load memory", .{}), |
| 1648 | errdefer self.register_manager.unlockReg(reg_lock); | | |
| 1649 | | | |
| 1650 | try self.genSetReg(ptr_ty, reg, src_ptr); | | |
| 1651 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); | | |
| 1652 | }, | | |
| 1653 | .load_symbol => { | 1667 | .load_symbol => { |
| 1654 | const reg = try self.copyToTmpRegister(ptr_ty, src_ptr); | 1668 | const reg = try self.copyToTmpRegister(ptr_ty, src_ptr); |
| 1655 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); | 1669 | try self.load(dst_mcv, .{ .register = reg }, ptr_ty); |
| ... | @@ -1675,7 +1689,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1675,7 +1689,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 1675 | // The MCValue that holds the pointer can be re-used as the value. | 1689 | // The MCValue that holds the pointer can be re-used as the value. |
| 1676 | break :blk ptr; | 1690 | break :blk ptr; |
| 1677 | } else { | 1691 | } else { |
| 1678 | break :blk try self.allocRegOrMem(inst, true); | 1692 | // TODO: set this to true, will need to implement register version of arrays and structs |
| | 1693 | break :blk try self.allocRegOrMem(inst, false); |
| 1679 | } | 1694 | } |
| 1680 | }; | 1695 | }; |
| 1681 | try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand)); | 1696 | try self.load(dst_mcv, ptr, self.typeOf(ty_op.operand)); |
| ... | @@ -1750,7 +1765,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1750,7 +1765,13 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1750 | const field_ty = struct_ty.structFieldType(index, mod); | 1765 | const field_ty = struct_ty.structFieldType(index, mod); |
| 1751 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; | 1766 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 1752 | | 1767 | |
| 1753 | const field_off = @as(u32, @intCast(struct_ty.structFieldOffset(index, mod))); | 1768 | const field_off: u32 = switch (struct_ty.containerLayout(mod)) { |
| | 1769 | .Auto, .Extern => @intCast(struct_ty.structFieldOffset(index, mod) * 8), |
| | 1770 | .Packed => if (mod.typeToStruct(struct_ty)) |struct_type| |
| | 1771 | mod.structPackedFieldBitOffset(struct_type, index) |
| | 1772 | else |
| | 1773 | 0, |
| | 1774 | }; |
| 1754 | | 1775 | |
| 1755 | switch (src_mcv) { | 1776 | switch (src_mcv) { |
| 1756 | .dead, .unreach => unreachable, | 1777 | .dead, .unreach => unreachable, |
| ... | @@ -1778,10 +1799,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1778,10 +1799,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1778 | }, | 1799 | }, |
| 1779 | }, | 1800 | }, |
| 1780 | }); | 1801 | }); |
| | 1802 | |
| | 1803 | return self.fail("TODO: airStructFieldVal register with field_off > 0", .{}); |
| 1781 | } | 1804 | } |
| 1782 | | 1805 | |
| 1783 | break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv); | 1806 | break :result if (field_off == 0) dst_mcv else try self.copyToNewRegister(inst, dst_mcv); |
| 1784 | }, | 1807 | }, |
| | 1808 | .stack_offset => |off| { |
| | 1809 | break :result MCValue{ .stack_offset = off + field_off }; |
| | 1810 | }, |
| 1785 | else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}), | 1811 | else => return self.fail("TODO: airStructField {s}", .{@tagName(src_mcv)}), |
| 1786 | } | 1812 | } |
| 1787 | }; | 1813 | }; |
| ... | @@ -2435,7 +2461,8 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index, target: Mir.Inst.Index) !void | ... | @@ -2435,7 +2461,8 @@ fn performReloc(self: *Self, inst: Mir.Inst.Index, target: Mir.Inst.Index) !void |
| 2435 | .bne, | 2461 | .bne, |
| 2436 | .beq, | 2462 | .beq, |
| 2437 | => self.mir_instructions.items(.data)[inst].b_type.inst = target, | 2463 | => self.mir_instructions.items(.data)[inst].b_type.inst = target, |
| 2438 | .jal => self.mir_instructions.items(.data)[inst].j_type.inst = target, | 2464 | .jal, |
| | 2465 | => self.mir_instructions.items(.data)[inst].j_type.inst = target, |
| 2439 | else => return self.fail("TODO: performReloc {s}", .{@tagName(tag)}), | 2466 | else => return self.fail("TODO: performReloc {s}", .{@tagName(tag)}), |
| 2440 | } | 2467 | } |
| 2441 | } | 2468 | } |
| ... | @@ -2614,6 +2641,7 @@ fn setValue(self: *Self, ty: Type, dst_val: MCValue, src_val: MCValue) !void { | ... | @@ -2614,6 +2641,7 @@ fn setValue(self: *Self, ty: Type, dst_val: MCValue, src_val: MCValue) !void { |
| 2614 | if (dst_val == .none) return; | 2641 | if (dst_val == .none) return; |
| 2615 | | 2642 | |
| 2616 | if (!dst_val.isMutable()) { | 2643 | if (!dst_val.isMutable()) { |
| | 2644 | // panic so we can see the trace |
| 2617 | return std.debug.panic("tried to setValue immutable: {s}", .{@tagName(dst_val)}); | 2645 | return std.debug.panic("tried to setValue immutable: {s}", .{@tagName(dst_val)}); |
| 2618 | } | 2646 | } |
| 2619 | | 2647 | |
| ... | @@ -2649,8 +2677,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner | ... | @@ -2649,8 +2677,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner |
| 2649 | .register => |reg| { | 2677 | .register => |reg| { |
| 2650 | switch (abi_size) { | 2678 | switch (abi_size) { |
| 2651 | 1, 2, 4, 8 => { | 2679 | 1, 2, 4, 8 => { |
| 2652 | assert(std.mem.isAlignedGeneric(u32, stack_offset, abi_size)); | | |
| 2653 | | | |
| 2654 | const tag: Mir.Inst.Tag = switch (abi_size) { | 2680 | const tag: Mir.Inst.Tag = switch (abi_size) { |
| 2655 | 1 => .sb, | 2681 | 1 => .sb, |
| 2656 | 2 => .sh, | 2682 | 2 => .sh, |
| ... | @@ -2733,7 +2759,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner | ... | @@ -2733,7 +2759,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, src_val: MCValue) Inner |
| 2733 | // memcpy(src, dst, len) | 2759 | // memcpy(src, dst, len) |
| 2734 | try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg); | 2760 | try self.genInlineMemcpy(src_reg, dst_reg, len_reg, count_reg, tmp_reg); |
| 2735 | }, | 2761 | }, |
| 2736 | | | |
| 2737 | else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}), | 2762 | else => return self.fail("TODO: genSetStack {s}", .{@tagName(src_val)}), |
| 2738 | } | 2763 | } |
| 2739 | } | 2764 | } |