| ... | @@ -337,6 +337,8 @@ pub fn generate( | ... | @@ -337,6 +337,8 @@ pub fn generate( |
| 337 | }; | 337 | }; |
| 338 | defer { | 338 | defer { |
| 339 | function.stack.deinit(gpa); | 339 | function.stack.deinit(gpa); |
| | 340 | var block_it = function.blocks.valueIterator(); |
| | 341 | while (block_it.next()) |block| block.deinit(gpa); |
| 340 | function.blocks.deinit(gpa); | 342 | function.blocks.deinit(gpa); |
| 341 | function.inst_tracking.deinit(gpa); | 343 | function.inst_tracking.deinit(gpa); |
| 342 | function.const_tracking.deinit(gpa); | 344 | function.const_tracking.deinit(gpa); |
| ... | @@ -1184,7 +1186,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1184,7 +1186,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1184 | var it = self.register_manager.free_registers.iterator(.{ .kind = .unset }); | 1186 | var it = self.register_manager.free_registers.iterator(.{ .kind = .unset }); |
| 1185 | while (it.next()) |index| { | 1187 | while (it.next()) |index| { |
| 1186 | const tracked_inst = self.register_manager.registers[index]; | 1188 | const tracked_inst = self.register_manager.registers[index]; |
| 1187 | const tracking = self.getResolvedInstValue(tracked_inst).?; | 1189 | const tracking = self.getResolvedInstValue(tracked_inst); |
| 1188 | assert(RegisterManager.indexOfRegIntoTracked(switch (tracking.short) { | 1190 | assert(RegisterManager.indexOfRegIntoTracked(switch (tracking.short) { |
| 1189 | .register => |reg| reg, | 1191 | .register => |reg| reg, |
| 1190 | .register_overflow => |ro| ro.reg, | 1192 | .register_overflow => |ro| ro.reg, |
| ... | @@ -1232,7 +1234,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { | ... | @@ -1232,7 +1234,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { |
| 1232 | const air_tags = self.air.instructions.items(.tag); | 1234 | const air_tags = self.air.instructions.items(.tag); |
| 1233 | if (air_tags[inst] == .constant) return; | 1235 | if (air_tags[inst] == .constant) return; |
| 1234 | log.debug("%{d} => {}", .{ inst, MCValue.dead }); | 1236 | log.debug("%{d} => {}", .{ inst, MCValue.dead }); |
| 1235 | if (self.getResolvedInstValue(inst)) |tracking| tracking.die(self); | 1237 | self.inst_tracking.getPtr(inst).?.die(self); |
| 1236 | } | 1238 | } |
| 1237 | | 1239 | |
| 1238 | /// Called when there are no operands, and the instruction is always unreferenced. | 1240 | /// Called when there are no operands, and the instruction is always unreferenced. |
| ... | @@ -1378,7 +1380,7 @@ fn saveState(self: *Self) !State { | ... | @@ -1378,7 +1380,7 @@ fn saveState(self: *Self) !State { |
| 1378 | return state; | 1380 | return state; |
| 1379 | } | 1381 | } |
| 1380 | | 1382 | |
| 1381 | fn restoreState(self: *Self, state: State, comptime opts: struct { | 1383 | fn restoreState(self: *Self, state: State, deaths: []u32, comptime opts: struct { |
| 1382 | emit_instructions: bool, | 1384 | emit_instructions: bool, |
| 1383 | update_tracking: bool, | 1385 | update_tracking: bool, |
| 1384 | resurrect: bool, | 1386 | resurrect: bool, |
| ... | @@ -1389,8 +1391,16 @@ fn restoreState(self: *Self, state: State, comptime opts: struct { | ... | @@ -1389,8 +1391,16 @@ fn restoreState(self: *Self, state: State, comptime opts: struct { |
| 1389 | self.inst_tracking.shrinkRetainingCapacity(state.inst_tracking_len); | 1391 | self.inst_tracking.shrinkRetainingCapacity(state.inst_tracking_len); |
| 1390 | } | 1392 | } |
| 1391 | | 1393 | |
| 1392 | if (opts.resurrect) for (self.inst_tracking.values()) |*tracking| | 1394 | if (opts.resurrect) { |
| 1393 | tracking.resurrect(state.scope_generation); | 1395 | var death_i: usize = 0; |
| | 1396 | for (self.inst_tracking.values()[0..state.inst_tracking_len], 0..) |*tracking, tracking_i| { |
| | 1397 | if (death_i < deaths.len and deaths[death_i] == tracking_i) { |
| | 1398 | // oops, it was actually a death instead |
| | 1399 | death_i += 1; |
| | 1400 | tracking.die(self); |
| | 1401 | } else tracking.resurrect(state.scope_generation); |
| | 1402 | } |
| | 1403 | } else assert(deaths.len == 0); |
| 1394 | | 1404 | |
| 1395 | for (0..state.registers.len) |index| { | 1405 | for (0..state.registers.len) |index| { |
| 1396 | const current_maybe_inst = if (self.register_manager.free_registers.isSet(index)) | 1406 | const current_maybe_inst = if (self.register_manager.free_registers.isSet(index)) |
| ... | @@ -3616,7 +3626,7 @@ fn reuseOperand( | ... | @@ -3616,7 +3626,7 @@ fn reuseOperand( |
| 3616 | | 3626 | |
| 3617 | // Prevent the operand deaths processing code from deallocating it. | 3627 | // Prevent the operand deaths processing code from deallocating it. |
| 3618 | self.liveness.clearOperandDeath(inst, op_index); | 3628 | self.liveness.clearOperandDeath(inst, op_index); |
| 3619 | if (self.getResolvedInstValue(Air.refToIndex(operand).?)) |tracking| tracking.reuse(self); | 3629 | self.getResolvedInstValue(Air.refToIndex(operand).?).reuse(self); |
| 3620 | | 3630 | |
| 3621 | return true; | 3631 | return true; |
| 3622 | } | 3632 | } |
| ... | @@ -6009,9 +6019,8 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6009,9 +6019,8 @@ fn airTry(self: *Self, inst: Air.Inst.Index) !void { |
| 6009 | const extra = self.air.extraData(Air.Try, pl_op.payload); | 6019 | const extra = self.air.extraData(Air.Try, pl_op.payload); |
| 6010 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; | 6020 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 6011 | const err_union_ty = self.air.typeOf(pl_op.operand); | 6021 | const err_union_ty = self.air.typeOf(pl_op.operand); |
| 6012 | const err_union = try self.resolveInst(pl_op.operand); | 6022 | const result = try self.genTry(inst, pl_op.operand, body, err_union_ty, false); |
| 6013 | const result = try self.genTry(inst, err_union, body, err_union_ty, false); | 6023 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 6014 | return self.finishAir(inst, result, .{ pl_op.operand, .none, .none }); | | |
| 6015 | } | 6024 | } |
| 6016 | | 6025 | |
| 6017 | fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { | 6026 | fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -6019,15 +6028,14 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6019,15 +6028,14 @@ fn airTryPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 6019 | const extra = self.air.extraData(Air.TryPtr, ty_pl.payload); | 6028 | const extra = self.air.extraData(Air.TryPtr, ty_pl.payload); |
| 6020 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; | 6029 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 6021 | const err_union_ty = self.air.typeOf(extra.data.ptr).childType(); | 6030 | const err_union_ty = self.air.typeOf(extra.data.ptr).childType(); |
| 6022 | const err_union_ptr = try self.resolveInst(extra.data.ptr); | 6031 | const result = try self.genTry(inst, extra.data.ptr, body, err_union_ty, true); |
| 6023 | const result = try self.genTry(inst, err_union_ptr, body, err_union_ty, true); | 6032 | return self.finishAir(inst, result, .{ .none, .none, .none }); |
| 6024 | return self.finishAir(inst, result, .{ extra.data.ptr, .none, .none }); | | |
| 6025 | } | 6033 | } |
| 6026 | | 6034 | |
| 6027 | fn genTry( | 6035 | fn genTry( |
| 6028 | self: *Self, | 6036 | self: *Self, |
| 6029 | inst: Air.Inst.Index, | 6037 | inst: Air.Inst.Index, |
| 6030 | err_union: MCValue, | 6038 | err_union: Air.Inst.Ref, |
| 6031 | body: []const Air.Inst.Index, | 6039 | body: []const Air.Inst.Index, |
| 6032 | err_union_ty: Type, | 6040 | err_union_ty: Type, |
| 6033 | operand_is_ptr: bool, | 6041 | operand_is_ptr: bool, |
| ... | @@ -6035,14 +6043,37 @@ fn genTry( | ... | @@ -6035,14 +6043,37 @@ fn genTry( |
| 6035 | if (operand_is_ptr) { | 6043 | if (operand_is_ptr) { |
| 6036 | return self.fail("TODO genTry for pointers", .{}); | 6044 | return self.fail("TODO genTry for pointers", .{}); |
| 6037 | } | 6045 | } |
| 6038 | const is_err_mcv = try self.isErr(null, err_union_ty, err_union); | 6046 | const liveness_cond_br = self.liveness.getCondBr(inst); |
| | 6047 | |
| | 6048 | const err_union_mcv = try self.resolveInst(err_union); |
| | 6049 | const is_err_mcv = try self.isErr(null, err_union_ty, err_union_mcv); |
| | 6050 | |
| 6039 | const reloc = try self.genCondBrMir(Type.anyerror, is_err_mcv); | 6051 | const reloc = try self.genCondBrMir(Type.anyerror, is_err_mcv); |
| | 6052 | |
| | 6053 | if (self.liveness.operandDies(inst, 0)) { |
| | 6054 | if (Air.refToIndex(err_union)) |err_union_inst| self.processDeath(err_union_inst); |
| | 6055 | } |
| | 6056 | |
| | 6057 | self.scope_generation += 1; |
| | 6058 | const state = try self.saveState(); |
| | 6059 | |
| | 6060 | for (liveness_cond_br.else_deaths) |operand| self.processDeath(operand); |
| 6040 | try self.genBody(body); | 6061 | try self.genBody(body); |
| | 6062 | try self.restoreState(state, &.{}, .{ |
| | 6063 | .emit_instructions = false, |
| | 6064 | .update_tracking = true, |
| | 6065 | .resurrect = true, |
| | 6066 | .close_scope = true, |
| | 6067 | }); |
| | 6068 | |
| 6041 | try self.performReloc(reloc); | 6069 | try self.performReloc(reloc); |
| | 6070 | |
| | 6071 | for (liveness_cond_br.then_deaths) |operand| self.processDeath(operand); |
| | 6072 | |
| 6042 | const result = if (self.liveness.isUnused(inst)) | 6073 | const result = if (self.liveness.isUnused(inst)) |
| 6043 | .unreach | 6074 | .unreach |
| 6044 | else | 6075 | else |
| 6045 | try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, err_union); | 6076 | try self.genUnwrapErrorUnionPayloadMir(inst, err_union_ty, err_union_mcv); |
| 6046 | return result; | 6077 | return result; |
| 6047 | } | 6078 | } |
| 6048 | | 6079 | |
| ... | @@ -6123,7 +6154,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6123,7 +6154,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 6123 | const extra = self.air.extraData(Air.CondBr, pl_op.payload); | 6154 | const extra = self.air.extraData(Air.CondBr, pl_op.payload); |
| 6124 | const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len]; | 6155 | const then_body = self.air.extra[extra.end..][0..extra.data.then_body_len]; |
| 6125 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | 6156 | const else_body = self.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| 6126 | const liveness_condbr = self.liveness.getCondBr(inst); | 6157 | const liveness_cond_br = self.liveness.getCondBr(inst); |
| 6127 | | 6158 | |
| 6128 | const reloc = try self.genCondBrMir(cond_ty, cond); | 6159 | const reloc = try self.genCondBrMir(cond_ty, cond); |
| 6129 | | 6160 | |
| ... | @@ -6139,9 +6170,9 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6139,9 +6170,9 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 6139 | self.scope_generation += 1; | 6170 | self.scope_generation += 1; |
| 6140 | const inner_state = try self.saveState(); | 6171 | const inner_state = try self.saveState(); |
| 6141 | | 6172 | |
| 6142 | for (liveness_condbr.then_deaths) |operand| self.processDeath(operand); | 6173 | for (liveness_cond_br.then_deaths) |operand| self.processDeath(operand); |
| 6143 | try self.genBody(then_body); | 6174 | try self.genBody(then_body); |
| 6144 | try self.restoreState(inner_state, .{ | 6175 | try self.restoreState(inner_state, &.{}, .{ |
| 6145 | .emit_instructions = false, | 6176 | .emit_instructions = false, |
| 6146 | .update_tracking = true, | 6177 | .update_tracking = true, |
| 6147 | .resurrect = true, | 6178 | .resurrect = true, |
| ... | @@ -6150,16 +6181,16 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6150,16 +6181,16 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 6150 | | 6181 | |
| 6151 | try self.performReloc(reloc); | 6182 | try self.performReloc(reloc); |
| 6152 | | 6183 | |
| 6153 | for (liveness_condbr.else_deaths) |operand| self.processDeath(operand); | 6184 | for (liveness_cond_br.else_deaths) |operand| self.processDeath(operand); |
| 6154 | try self.genBody(else_body); | 6185 | try self.genBody(else_body); |
| 6155 | try self.restoreState(inner_state, .{ | 6186 | try self.restoreState(inner_state, &.{}, .{ |
| 6156 | .emit_instructions = false, | 6187 | .emit_instructions = false, |
| 6157 | .update_tracking = true, | 6188 | .update_tracking = true, |
| 6158 | .resurrect = true, | 6189 | .resurrect = true, |
| 6159 | .close_scope = true, | 6190 | .close_scope = true, |
| 6160 | }); | 6191 | }); |
| 6161 | } | 6192 | } |
| 6162 | try self.restoreState(outer_state, .{ | 6193 | try self.restoreState(outer_state, &.{}, .{ |
| 6163 | .emit_instructions = false, | 6194 | .emit_instructions = false, |
| 6164 | .update_tracking = false, | 6195 | .update_tracking = false, |
| 6165 | .resurrect = false, | 6196 | .resurrect = false, |
| ... | @@ -6473,7 +6504,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6473,7 +6504,7 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 6473 | const state = try self.saveState(); | 6504 | const state = try self.saveState(); |
| 6474 | | 6505 | |
| 6475 | try self.genBody(body); | 6506 | try self.genBody(body); |
| 6476 | try self.restoreState(state, .{ | 6507 | try self.restoreState(state, &.{}, .{ |
| 6477 | .emit_instructions = true, | 6508 | .emit_instructions = true, |
| 6478 | .update_tracking = false, | 6509 | .update_tracking = false, |
| 6479 | .resurrect = false, | 6510 | .resurrect = false, |
| ... | @@ -6486,40 +6517,29 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6486,40 +6517,29 @@ fn airLoop(self: *Self, inst: Air.Inst.Index) !void { |
| 6486 | | 6517 | |
| 6487 | fn airBlock(self: *Self, inst: Air.Inst.Index) !void { | 6518 | fn airBlock(self: *Self, inst: Air.Inst.Index) !void { |
| 6488 | // A block is a setup to be able to jump to the end. | 6519 | // A block is a setup to be able to jump to the end. |
| 6489 | const ty = self.air.typeOfIndex(inst); | 6520 | self.inst_tracking.putAssumeCapacityNoClobber(inst, InstTracking.init(.unreach)); |
| 6490 | | | |
| 6491 | // Here we use .{ .long = .unreach } to represent a null value so that the | | |
| 6492 | // first break instruction will choose a MCValue for the block result and | | |
| 6493 | // overwrite this field. Following break instructions will use that MCValue | | |
| 6494 | // to put their block results. | | |
| 6495 | self.inst_tracking.putAssumeCapacityNoClobber(inst, .{ | | |
| 6496 | .long = .unreach, | | |
| 6497 | .short = if (ty.isNoReturn()) .unreach else .none, | | |
| 6498 | }); | | |
| 6499 | | 6521 | |
| 6500 | self.scope_generation += 1; | 6522 | self.scope_generation += 1; |
| 6501 | try self.blocks.putNoClobber(self.gpa, inst, .{ .state = self.initRetroactiveState() }); | 6523 | try self.blocks.putNoClobber(self.gpa, inst, .{ .state = self.initRetroactiveState() }); |
| 6502 | defer { | | |
| 6503 | var block_data = self.blocks.fetchRemove(inst).?.value; | | |
| 6504 | block_data.deinit(self.gpa); | | |
| 6505 | } | | |
| 6506 | | 6524 | |
| 6507 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 6525 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 6508 | const extra = self.air.extraData(Air.Block, ty_pl.payload); | 6526 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| 6509 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; | 6527 | const body = self.air.extra[extra.end..][0..extra.data.body_len]; |
| 6510 | try self.genBody(body); | 6528 | try self.genBody(body); |
| 6511 | | 6529 | |
| 6512 | const tracking = self.inst_tracking.getPtr(inst).?; | 6530 | var block_data = self.blocks.fetchRemove(inst).?; |
| 6513 | const block_data = self.blocks.getPtr(inst).?; | 6531 | defer block_data.value.deinit(self.gpa); |
| 6514 | for (block_data.deaths.items) |tracking_index| self.inst_tracking.values()[tracking_index].die(self); | 6532 | if (block_data.value.relocs.items.len > 0) { |
| 6515 | if (tracking.short != .unreach) try self.restoreState(block_data.state, .{ | 6533 | try self.restoreState(block_data.value.state, block_data.value.deaths.items, .{ |
| 6516 | .emit_instructions = false, | 6534 | .emit_instructions = false, |
| 6517 | .update_tracking = true, | 6535 | .update_tracking = true, |
| 6518 | .resurrect = false, | 6536 | .resurrect = true, |
| 6519 | .close_scope = true, | 6537 | .close_scope = true, |
| 6520 | }); | 6538 | }); |
| 6521 | for (block_data.relocs.items) |reloc| try self.performReloc(reloc); | 6539 | for (block_data.value.relocs.items) |reloc| try self.performReloc(reloc); |
| | 6540 | } |
| 6522 | | 6541 | |
| | 6542 | const tracking = self.inst_tracking.getPtr(inst).?; |
| 6523 | if (self.liveness.isUnused(inst)) tracking.die(self); | 6543 | if (self.liveness.isUnused(inst)) tracking.die(self); |
| 6524 | self.getValue(tracking.short, inst); | 6544 | self.getValue(tracking.short, inst); |
| 6525 | self.finishAirBookkeeping(); | 6545 | self.finishAirBookkeeping(); |
| ... | @@ -6569,7 +6589,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6569,7 +6589,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 6569 | for (liveness.deaths[case_i]) |operand| self.processDeath(operand); | 6589 | for (liveness.deaths[case_i]) |operand| self.processDeath(operand); |
| 6570 | | 6590 | |
| 6571 | try self.genBody(case_body); | 6591 | try self.genBody(case_body); |
| 6572 | try self.restoreState(inner_state, .{ | 6592 | try self.restoreState(inner_state, &.{}, .{ |
| 6573 | .emit_instructions = false, | 6593 | .emit_instructions = false, |
| 6574 | .update_tracking = true, | 6594 | .update_tracking = true, |
| 6575 | .resurrect = true, | 6595 | .resurrect = true, |
| ... | @@ -6586,7 +6606,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6586,7 +6606,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 6586 | for (liveness.deaths[else_deaths]) |operand| self.processDeath(operand); | 6606 | for (liveness.deaths[else_deaths]) |operand| self.processDeath(operand); |
| 6587 | | 6607 | |
| 6588 | try self.genBody(else_body); | 6608 | try self.genBody(else_body); |
| 6589 | try self.restoreState(inner_state, .{ | 6609 | try self.restoreState(inner_state, &.{}, .{ |
| 6590 | .emit_instructions = false, | 6610 | .emit_instructions = false, |
| 6591 | .update_tracking = true, | 6611 | .update_tracking = true, |
| 6592 | .resurrect = true, | 6612 | .resurrect = true, |
| ... | @@ -6594,7 +6614,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6594,7 +6614,7 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 6594 | }); | 6614 | }); |
| 6595 | } | 6615 | } |
| 6596 | } | 6616 | } |
| 6597 | try self.restoreState(outer_state, .{ | 6617 | try self.restoreState(outer_state, &.{}, .{ |
| 6598 | .emit_instructions = false, | 6618 | .emit_instructions = false, |
| 6599 | .update_tracking = false, | 6619 | .update_tracking = false, |
| 6600 | .resurrect = false, | 6620 | .resurrect = false, |
| ... | @@ -6620,58 +6640,64 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { | ... | @@ -6620,58 +6640,64 @@ fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void { |
| 6620 | | 6640 | |
| 6621 | fn airBr(self: *Self, inst: Air.Inst.Index) !void { | 6641 | fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 6622 | const br = self.air.instructions.items(.data)[inst].br; | 6642 | const br = self.air.instructions.items(.data)[inst].br; |
| | 6643 | const src_mcv = try self.resolveInst(br.operand); |
| | 6644 | |
| 6623 | const block_ty = self.air.typeOfIndex(br.block_inst); | 6645 | const block_ty = self.air.typeOfIndex(br.block_inst); |
| 6624 | const block_unused = | 6646 | const block_unused = |
| 6625 | !block_ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(br.block_inst); | 6647 | !block_ty.hasRuntimeBitsIgnoreComptime() or self.liveness.isUnused(br.block_inst); |
| 6626 | | | |
| 6627 | // Process operand death early so that it is properly accounted for in the State below. | | |
| 6628 | const src_mcv = try self.resolveInst(br.operand); | | |
| 6629 | if (self.liveness.operandDies(inst, 0)) { | | |
| 6630 | if (Air.refToIndex(br.operand)) |op_inst| self.processDeath(op_inst); | | |
| 6631 | } | | |
| 6632 | | | |
| 6633 | const block_tracking = self.inst_tracking.getPtr(br.block_inst).?; | 6648 | const block_tracking = self.inst_tracking.getPtr(br.block_inst).?; |
| 6634 | const block_data = self.blocks.getPtr(br.block_inst).?; | 6649 | const block_data = self.blocks.getPtr(br.block_inst).?; |
| 6635 | if (block_tracking.long == .unreach) { | | |
| 6636 | // .unreach is used to mean that we are the first branch | | |
| 6637 | | 6650 | |
| | 6651 | if (block_data.relocs.items.len == 0) { |
| 6638 | // We need to compute a list of deaths for later. This list needs to include | 6652 | // We need to compute a list of deaths for later. This list needs to include |
| 6639 | // instructions that was born before, and has died since, the target block. | 6653 | // instructions that was born before, and has died since, the target block. |
| 6640 | for (self.inst_tracking.values()[0..block_data.state.inst_tracking_len], 0..) | | 6654 | for ( |
| 6641 | *tracking, | 6655 | self.inst_tracking.values()[0..block_data.state.inst_tracking_len], |
| 6642 | tracked_index, | 6656 | 0.., |
| 6643 | | switch (tracking.short) { | 6657 | ) |*tracking, tracked_index| switch (tracking.short) { |
| 6644 | .dead => |die_generation| if (die_generation >= block_data.state.scope_generation) | 6658 | .dead => |die_generation| if (die_generation >= block_data.state.scope_generation) |
| 6645 | try block_data.deaths.append(self.gpa, @intCast(u32, tracked_index)), | 6659 | try block_data.deaths.append(self.gpa, @intCast(u32, tracked_index)), |
| 6646 | else => {}, | 6660 | else => {}, |
| 6647 | }; | 6661 | }; |
| 6648 | | 6662 | |
| 6649 | const result = result: { | 6663 | block_tracking.* = InstTracking.init(result: { |
| 6650 | if (block_unused) break :result .none; | 6664 | if (block_unused) break :result .none; |
| 6651 | if (self.reuseOperand(inst, br.operand, 0, src_mcv)) break :result src_mcv; | 6665 | if (self.reuseOperand(inst, br.operand, 0, src_mcv)) { |
| | 6666 | // Fix instruction tracking |
| | 6667 | switch (src_mcv) { |
| | 6668 | .register => |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |index| { |
| | 6669 | self.register_manager.registers[index] = br.block_inst; |
| | 6670 | }, |
| | 6671 | else => {}, |
| | 6672 | } |
| | 6673 | break :result src_mcv; |
| | 6674 | } |
| 6652 | | 6675 | |
| 6653 | const new_mcv = try self.allocRegOrMem(br.block_inst, true); | 6676 | const new_mcv = try self.allocRegOrMem(br.block_inst, true); |
| 6654 | try self.setRegOrMem(block_ty, new_mcv, src_mcv); | 6677 | try self.setRegOrMem(block_ty, new_mcv, src_mcv); |
| 6655 | break :result new_mcv; | 6678 | break :result new_mcv; |
| 6656 | }; | | |
| 6657 | block_tracking.* = InstTracking.init(result); | | |
| 6658 | try self.saveRetroactiveState(&block_data.state); | | |
| 6659 | self.freeValue(result); | | |
| 6660 | } else { | | |
| 6661 | if (!block_unused) try self.setRegOrMem(block_ty, block_tracking.short, src_mcv); | | |
| 6662 | try self.restoreState(block_data.state, .{ | | |
| 6663 | .emit_instructions = true, | | |
| 6664 | .update_tracking = false, | | |
| 6665 | .resurrect = false, | | |
| 6666 | .close_scope = false, | | |
| 6667 | }); | 6679 | }); |
| | 6680 | } else if (!block_unused) try self.setRegOrMem(block_ty, block_tracking.short, src_mcv); |
| | 6681 | |
| | 6682 | // Process operand death so that it is properly accounted for in the State below. |
| | 6683 | if (self.liveness.operandDies(inst, 0)) { |
| | 6684 | if (Air.refToIndex(br.operand)) |op_inst| self.processDeath(op_inst); |
| 6668 | } | 6685 | } |
| 6669 | | 6686 | |
| | 6687 | if (block_data.relocs.items.len == 0) { |
| | 6688 | try self.saveRetroactiveState(&block_data.state); |
| | 6689 | block_tracking.die(self); |
| | 6690 | } else try self.restoreState(block_data.state, &.{}, .{ |
| | 6691 | .emit_instructions = true, |
| | 6692 | .update_tracking = false, |
| | 6693 | .resurrect = false, |
| | 6694 | .close_scope = false, |
| | 6695 | }); |
| | 6696 | |
| 6670 | // Emit a jump with a relocation. It will be patched up after the block ends. | 6697 | // Emit a jump with a relocation. It will be patched up after the block ends. |
| 6671 | try block_data.relocs.ensureUnusedCapacity(self.gpa, 1); | | |
| 6672 | // Leave the jump offset undefined | 6698 | // Leave the jump offset undefined |
| 6673 | const jmp_reloc = try self.asmJmpReloc(undefined); | 6699 | const jmp_reloc = try self.asmJmpReloc(undefined); |
| 6674 | block_data.relocs.appendAssumeCapacity(jmp_reloc); | 6700 | try block_data.relocs.append(self.gpa, jmp_reloc); |
| 6675 | | 6701 | |
| 6676 | self.finishAirBookkeeping(); | 6702 | self.finishAirBookkeeping(); |
| 6677 | } | 6703 | } |
| ... | @@ -8636,7 +8662,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { | ... | @@ -8636,7 +8662,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 8636 | else => self.inst_tracking.getPtr(inst).?, | 8662 | else => self.inst_tracking.getPtr(inst).?, |
| 8637 | }.short; | 8663 | }.short; |
| 8638 | switch (mcv) { | 8664 | switch (mcv) { |
| 8639 | .none, .unreach => unreachable, | 8665 | .none, .unreach, .dead => unreachable, |
| 8640 | else => return mcv, | 8666 | else => return mcv, |
| 8641 | } | 8667 | } |
| 8642 | } | 8668 | } |
| ... | @@ -8644,15 +8670,14 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { | ... | @@ -8644,15 +8670,14 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue { |
| 8644 | return self.genTypedValue(.{ .ty = ty, .val = self.air.value(ref).? }); | 8670 | return self.genTypedValue(.{ .ty = ty, .val = self.air.value(ref).? }); |
| 8645 | } | 8671 | } |
| 8646 | | 8672 | |
| 8647 | fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) ?*InstTracking { | 8673 | fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking { |
| 8648 | const tracking = switch (self.air.instructions.items(.tag)[inst]) { | 8674 | const tracking = switch (self.air.instructions.items(.tag)[inst]) { |
| 8649 | .constant => self.const_tracking.getPtr(inst) orelse return null, | 8675 | .constant => &self.const_tracking, |
| 8650 | .const_ty => unreachable, | 8676 | .const_ty => unreachable, |
| 8651 | else => self.inst_tracking.getPtr(inst).?, | 8677 | else => &self.inst_tracking, |
| 8652 | }; | 8678 | }.getPtr(inst).?; |
| 8653 | return switch (tracking.short) { | 8679 | return switch (tracking.short) { |
| 8654 | .unreach => unreachable, | 8680 | .none, .unreach, .dead => unreachable, |
| 8655 | .dead => null, | | |
| 8656 | else => tracking, | 8681 | else => tracking, |
| 8657 | }; | 8682 | }; |
| 8658 | } | 8683 | } |