| ... | @@ -789,8 +789,13 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT | ... | @@ -789,8 +789,13 @@ fn iterateBigTomb(self: *Self, inst: Air.Inst.Index, operand_count: usize) !BigT |
| 789 | fn processDeath(self: *Self, ref: Air.Inst.Ref) void { | 789 | fn processDeath(self: *Self, ref: Air.Inst.Ref) void { |
| 790 | const inst = Air.refToIndex(ref) orelse return; | 790 | const inst = Air.refToIndex(ref) orelse return; |
| 791 | if (self.air.instructions.items(.tag)[inst] == .constant) return; | 791 | if (self.air.instructions.items(.tag)[inst] == .constant) return; |
| 792 | var value = self.values.get(ref) orelse return; | 792 | const value = self.values.getPtr(ref) orelse return; |
| 793 | value.free(self); | 793 | if (value.* != .local) return; |
| | 794 | std.debug.print("Decreasing reference for ref: %{?d}\n", .{Air.refToIndex(ref)}); |
| | 795 | value.local.references -= 1; // if this panics, a call to `reuseOperand` was forgotten by the developer |
| | 796 | if (value.local.references == 0) { |
| | 797 | value.free(self); |
| | 798 | } |
| 794 | } | 799 | } |
| 795 | | 800 | |
| 796 | /// Appends a MIR instruction and returns its index within the list of instructions | 801 | /// Appends a MIR instruction and returns its index within the list of instructions |
| ... | @@ -909,10 +914,29 @@ fn emitWValue(self: *Self, value: WValue) InnerError!void { | ... | @@ -909,10 +914,29 @@ fn emitWValue(self: *Self, value: WValue) InnerError!void { |
| 909 | try self.addInst(.{ .tag = .memory_address, .data = .{ .payload = extra_index } }); | 914 | try self.addInst(.{ .tag = .memory_address, .data = .{ .payload = extra_index } }); |
| 910 | }, | 915 | }, |
| 911 | .function_index => |index| try self.addLabel(.function_index, index), // write function index and generate relocation | 916 | .function_index => |index| try self.addLabel(.function_index, index), // write function index and generate relocation |
| 912 | .stack_offset => try self.addLabel(.local_get, self.bottom_stack_value.local), // caller must ensure to address the offset | 917 | .stack_offset => try self.addLabel(.local_get, self.bottom_stack_value.local.value), // caller must ensure to address the offset |
| 913 | } | 918 | } |
| 914 | } | 919 | } |
| 915 | | 920 | |
| | 921 | /// If given a local or stack-offset, increases the reference count by 1. |
| | 922 | /// The old `WValue` found at instruction `ref` is then replaced by the |
| | 923 | /// modified `WValue` and returned. When given a non-local or non-stack-offset, |
| | 924 | /// returns the given `operand` itself instead. |
| | 925 | fn reuseOperand(self: *Self, ref: Air.Inst.Ref, operand: WValue) WValue { |
| | 926 | if (operand != .local and operand != .stack_offset) return operand; |
| | 927 | var copy = operand; |
| | 928 | switch (copy) { |
| | 929 | .local => |*local| local.references += 1, |
| | 930 | .stack_offset => |*stack_offset| stack_offset.references += 1, |
| | 931 | else => unreachable, |
| | 932 | } |
| | 933 | |
| | 934 | const gop = self.values.getOrPutAssumeCapacity(ref); |
| | 935 | assert(gop.found_existing); |
| | 936 | gop.value_ptr.* = copy; |
| | 937 | return copy; |
| | 938 | } |
| | 939 | |
| 916 | /// Creates one locals for a given `Type`. | 940 | /// Creates one locals for a given `Type`. |
| 917 | /// Returns a corresponding `Wvalue` with `local` as active tag | 941 | /// Returns a corresponding `Wvalue` with `local` as active tag |
| 918 | fn allocLocal(self: *Self, ty: Type) InnerError!WValue { | 942 | fn allocLocal(self: *Self, ty: Type) InnerError!WValue { |
| ... | @@ -2956,7 +2980,8 @@ fn airUnreachable(self: *Self, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2956,7 +2980,8 @@ fn airUnreachable(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 2956 | fn airBitcast(self: *Self, inst: Air.Inst.Index) InnerError!void { | 2980 | fn airBitcast(self: *Self, inst: Air.Inst.Index) InnerError!void { |
| 2957 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 2981 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 2958 | const result = if (!self.liveness.isUnused(inst)) result: { | 2982 | const result = if (!self.liveness.isUnused(inst)) result: { |
| 2959 | break :result try self.resolveInst(ty_op.operand); | 2983 | const operand = try self.resolveInst(ty_op.operand); |
| | 2984 | break :result self.reuseOperand(ty_op.operand, operand); |
| 2960 | } else WValue{ .none = {} }; | 2985 | } else WValue{ .none = {} }; |
| 2961 | self.finishAir(inst, result, &.{}); | 2986 | self.finishAir(inst, result, &.{}); |
| 2962 | } | 2987 | } |