| ... | @@ -4277,6 +4277,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4277,6 +4277,7 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4277 | const extra = f.air.extraData(Air.CondBr, pl_op.payload); | 4277 | const extra = f.air.extraData(Air.CondBr, pl_op.payload); |
| 4278 | const then_body = f.air.extra[extra.end..][0..extra.data.then_body_len]; | 4278 | const then_body = f.air.extra[extra.end..][0..extra.data.then_body_len]; |
| 4279 | const else_body = f.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; | 4279 | const else_body = f.air.extra[extra.end + then_body.len ..][0..extra.data.else_body_len]; |
| | 4280 | const liveness_condbr = f.liveness.getCondBr(inst); |
| 4280 | const writer = f.object.writer(); | 4281 | const writer = f.object.writer(); |
| 4281 | | 4282 | |
| 4282 | // Keep using the original for the then branch; use a clone of the value | 4283 | // Keep using the original for the then branch; use a clone of the value |
| ... | @@ -4287,6 +4288,10 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4287,6 +4288,10 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4287 | var cloned_frees = try f.free_locals.clone(gpa); | 4288 | var cloned_frees = try f.free_locals.clone(gpa); |
| 4288 | defer cloned_frees.deinit(gpa); | 4289 | defer cloned_frees.deinit(gpa); |
| 4289 | | 4290 | |
| | 4291 | for (liveness_condbr.then_deaths) |operand| { |
| | 4292 | try die(f, inst, Air.indexToRef(operand)); |
| | 4293 | } |
| | 4294 | |
| 4290 | try writer.writeAll("if ("); | 4295 | try writer.writeAll("if ("); |
| 4291 | try f.writeCValue(writer, cond, .Other); | 4296 | try f.writeCValue(writer, cond, .Other); |
| 4292 | try writer.writeAll(") "); | 4297 | try writer.writeAll(") "); |
| ... | @@ -4296,6 +4301,9 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4296,6 +4301,9 @@ fn airCondBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4296 | f.value_map = cloned_map.move(); | 4301 | f.value_map = cloned_map.move(); |
| 4297 | f.free_locals.deinit(gpa); | 4302 | f.free_locals.deinit(gpa); |
| 4298 | f.free_locals = cloned_frees.move(); | 4303 | f.free_locals = cloned_frees.move(); |
| | 4304 | for (liveness_condbr.else_deaths) |operand| { |
| | 4305 | try die(f, inst, Air.indexToRef(operand)); |
| | 4306 | } |
| 4299 | try genBody(f, else_body); | 4307 | try genBody(f, else_body); |
| 4300 | try f.object.indent_writer.insertNewline(); | 4308 | try f.object.indent_writer.insertNewline(); |
| 4301 | | 4309 | |
| ... | @@ -4325,6 +4333,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4325,6 +4333,12 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4325 | f.object.indent_writer.pushIndent(); | 4333 | f.object.indent_writer.pushIndent(); |
| 4326 | | 4334 | |
| 4327 | const gpa = f.object.dg.gpa; | 4335 | const gpa = f.object.dg.gpa; |
| | 4336 | const liveness = try f.liveness.getSwitchBr(gpa, inst, switch_br.data.cases_len + 1); |
| | 4337 | defer gpa.free(liveness.deaths); |
| | 4338 | // On the final iteration we do not clone the map. This ensures that |
| | 4339 | // lowering proceeds after the switch_br taking into account the |
| | 4340 | // mutations to the liveness information. |
| | 4341 | const last_case_i = switch_br.data.cases_len - @boolToInt(switch_br.data.else_body_len == 0); |
| 4328 | var extra_index: usize = switch_br.end; | 4342 | var extra_index: usize = switch_br.end; |
| 4329 | var case_i: u32 = 0; | 4343 | var case_i: u32 = 0; |
| 4330 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { | 4344 | while (case_i < switch_br.data.cases_len) : (case_i += 1) { |
| ... | @@ -4344,15 +4358,16 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4344,15 +4358,16 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4344 | try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other); | 4358 | try f.object.dg.renderValue(writer, condition_ty, f.air.value(item).?, .Other); |
| 4345 | try writer.writeAll(": "); | 4359 | try writer.writeAll(": "); |
| 4346 | } | 4360 | } |
| 4347 | // On the final iteration we do not clone the map. This ensures that | 4361 | if (case_i != last_case_i) { |
| 4348 | // lowering proceeds after the switch_br taking into account the | | |
| 4349 | // mutations to the liveness information. | | |
| 4350 | // The case body must be noreturn so we don't need to insert a break. | | |
| 4351 | if (case_i < switch_br.data.cases_len - 1) { | | |
| 4352 | const old_value_map = f.value_map; | 4362 | const old_value_map = f.value_map; |
| 4353 | f.value_map = try old_value_map.clone(); | 4363 | f.value_map = try old_value_map.clone(); |
| 4354 | const old_free_locals = f.free_locals; | 4364 | const old_free_locals = f.free_locals; |
| 4355 | f.free_locals = try f.free_locals.clone(gpa); | 4365 | f.free_locals = try f.free_locals.clone(gpa); |
| | 4366 | |
| | 4367 | for (liveness.deaths[case_i]) |operand| { |
| | 4368 | try die(f, inst, Air.indexToRef(operand)); |
| | 4369 | } |
| | 4370 | |
| 4356 | defer { | 4371 | defer { |
| 4357 | f.value_map.deinit(); | 4372 | f.value_map.deinit(); |
| 4358 | f.free_locals.deinit(gpa); | 4373 | f.free_locals.deinit(gpa); |
| ... | @@ -4361,14 +4376,25 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4361,14 +4376,25 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4361 | } | 4376 | } |
| 4362 | try genBody(f, case_body); | 4377 | try genBody(f, case_body); |
| 4363 | } else { | 4378 | } else { |
| | 4379 | for (liveness.deaths[case_i]) |operand| { |
| | 4380 | try die(f, inst, Air.indexToRef(operand)); |
| | 4381 | } |
| 4364 | try genBody(f, case_body); | 4382 | try genBody(f, case_body); |
| 4365 | } | 4383 | } |
| | 4384 | // The case body must be noreturn so we don't need to insert a break. |
| 4366 | } | 4385 | } |
| 4367 | | 4386 | |
| 4368 | const else_body = f.air.extra[extra_index..][0..switch_br.data.else_body_len]; | 4387 | const else_body = f.air.extra[extra_index..][0..switch_br.data.else_body_len]; |
| 4369 | try f.object.indent_writer.insertNewline(); | 4388 | try f.object.indent_writer.insertNewline(); |
| 4370 | try writer.writeAll("default: "); | 4389 | if (else_body.len > 0) { |
| 4371 | try genBody(f, else_body); | 4390 | for (liveness.deaths[liveness.deaths.len - 1]) |operand| { |
| | 4391 | try die(f, inst, Air.indexToRef(operand)); |
| | 4392 | } |
| | 4393 | try writer.writeAll("default: "); |
| | 4394 | try genBody(f, else_body); |
| | 4395 | } else { |
| | 4396 | try writer.writeAll("default: zig_unreachable();"); |
| | 4397 | } |
| 4372 | try f.object.indent_writer.insertNewline(); | 4398 | try f.object.indent_writer.insertNewline(); |
| 4373 | | 4399 | |
| 4374 | f.object.indent_writer.popIndent(); | 4400 | f.object.indent_writer.popIndent(); |