authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-12 21:46:04-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-06-12 21:46:04-04:00
logcdf14baa45257a884fa20d8d992eb7be0d344005
treed062f65b5d39bb60c83a53297b29a586e1791660
parent0d62c929470458e30b888f76d029fff48d31fd3b
signaturelock-open Commit is signed but in an unrecognized format.

fix double nested peer result locations

```zig export fn entry(x: bool) i32 { return if (x) if (x) a else b else if (x) c else d; } ```

2 files changed, 45 insertions(+), 33 deletions(-)

src/all_types.hpp+6-5
...@@ -3649,10 +3649,16 @@ struct ResultLocReturn {...@@ -3649,10 +3649,16 @@ struct ResultLocReturn {
3649 ResultLoc base;3649 ResultLoc base;
3650};3650};
36513651
3652struct IrSuspendPosition {
3653 size_t basic_block_index;
3654 size_t instruction_index;
3655};
3656
3652struct ResultLocPeerParent {3657struct ResultLocPeerParent {
3653 ResultLoc base;3658 ResultLoc base;
36543659
3655 bool skipped;3660 bool skipped;
3661 bool done_resuming;
3656 ResultLoc *parent;3662 ResultLoc *parent;
3657 ResultLocPeer *peers;3663 ResultLocPeer *peers;
3658 size_t peer_count;3664 size_t peer_count;
...@@ -3660,11 +3666,6 @@ struct ResultLocPeerParent {...@@ -3660,11 +3666,6 @@ struct ResultLocPeerParent {
3660 IrInstruction *is_comptime;3666 IrInstruction *is_comptime;
3661};3667};
36623668
3663struct IrSuspendPosition {
3664 size_t basic_block_index;
3665 size_t instruction_index;
3666};
3667
3668struct ResultLocPeer {3669struct ResultLocPeer {
3669 ResultLoc base;3670 ResultLoc base;
36703671
src/ir.cpp+39-28
...@@ -16395,45 +16395,56 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh...@@ -16395,45 +16395,56 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
16395 }16395 }
1639616396
16397 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;16397 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
16398 if (peer_parent != nullptr && peer_parent->resolved_type == nullptr && !peer_parent->skipped) {16398 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming) {
16399 // Suspend the phi first so that it gets resumed last16399 if (peer_parent->resolved_type == nullptr) {
16400 ira->resume_stack.add_one();16400 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peer_count);
16401 for (size_t i = ira->resume_stack.length;;) {16401 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
16402 if (i <= 1) break;16402 ResultLocPeer *this_peer = &peer_parent->peers[i];
16403 i -= 1;16403
16404 ira->resume_stack.items[i] = ira->resume_stack.items[i-1];16404 IrInstruction *gen_instruction = this_peer->base.gen_instruction;
16405 if (gen_instruction == nullptr) {
16406 // unreachable instructions will cause implicit_elem_type to be null
16407 if (this_peer->base.implicit_elem_type == nullptr) {
16408 instructions[i] = ir_const_unreachable(ira, this_peer->base.source_instruction);
16409 } else {
16410 instructions[i] = ir_const(ira, this_peer->base.source_instruction,
16411 this_peer->base.implicit_elem_type);
16412 instructions[i]->value.special = ConstValSpecialRuntime;
16413 }
16414 } else {
16415 instructions[i] = gen_instruction;
16416 }
16417
16418 }
16419 ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, peer_parent->parent);
16420 peer_parent->resolved_type = ir_resolve_peer_types(ira,
16421 peer_parent->base.source_instruction->source_node, expected_type, instructions,
16422 peer_parent->peer_count);
16423
16424 // In case resolving the parent activates a suspend, do it now
16425 IrInstruction *parent_result_loc = ir_resolve_result(ira, &phi_instruction->base, peer_parent->parent,
16426 peer_parent->resolved_type, nullptr);
16427 if (parent_result_loc != nullptr &&
16428 (type_is_invalid(parent_result_loc->value.type) || instr_is_unreachable(parent_result_loc)))
16429 {
16430 return parent_result_loc;
16431 }
16405 }16432 }
16406 ira_suspend(ira, &phi_instruction->base, nullptr, &ira->resume_stack.items[0]);
1640716433
16408 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peer_count);16434 IrSuspendPosition suspend_pos;
16435 ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos);
16436 ira->resume_stack.append(suspend_pos);
16437
16409 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {16438 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
16410 ResultLocPeer *this_peer = &peer_parent->peers[i];
16411 ResultLocPeer *opposite_peer = &peer_parent->peers[peer_parent->peer_count - i - 1];16439 ResultLocPeer *opposite_peer = &peer_parent->peers[peer_parent->peer_count - i - 1];
16412
16413 IrInstruction *gen_instruction = this_peer->base.gen_instruction;
16414 if (gen_instruction == nullptr) {
16415 // unreachable instructions will cause implicit_elem_type to be null
16416 if (this_peer->base.implicit_elem_type == nullptr) {
16417 instructions[i] = ir_const_unreachable(ira, this_peer->base.source_instruction);
16418 } else {
16419 instructions[i] = ir_const(ira, this_peer->base.source_instruction,
16420 this_peer->base.implicit_elem_type);
16421 instructions[i]->value.special = ConstValSpecialRuntime;
16422 }
16423 } else {
16424 instructions[i] = gen_instruction;
16425 }
16426 if (opposite_peer->base.implicit_elem_type != nullptr &&16440 if (opposite_peer->base.implicit_elem_type != nullptr &&
16427 opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)16441 opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)
16428 {16442 {
16429 ira->resume_stack.append(opposite_peer->suspend_pos);16443 ira->resume_stack.append(opposite_peer->suspend_pos);
16430 }16444 }
16431 }16445 }
16432 ZigType *expected_type = ir_result_loc_expected_type(ira, &phi_instruction->base, peer_parent->parent);
16433 peer_parent->resolved_type = ir_resolve_peer_types(ira,
16434 peer_parent->base.source_instruction->source_node, expected_type, instructions,
16435 peer_parent->peer_count);
1643616446
16447 peer_parent->done_resuming = true;
16437 return ira_resume(ira);16448 return ira_resume(ira);
16438 }16449 }
1643916450