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
signature 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 {
36493649 ResultLoc base;
36503650};
36513651
3652struct IrSuspendPosition {
3653 size_t basic_block_index;
3654 size_t instruction_index;
3655};
3656
36523657struct ResultLocPeerParent {
36533658 ResultLoc base;
36543659
36553660 bool skipped;
3661 bool done_resuming;
36563662 ResultLoc *parent;
36573663 ResultLocPeer *peers;
36583664 size_t peer_count;
......@@ -3660,11 +3666,6 @@ struct ResultLocPeerParent {
36603666 IrInstruction *is_comptime;
36613667};
36623668
3663struct IrSuspendPosition {
3664 size_t basic_block_index;
3665 size_t instruction_index;
3666};
3667
36683669struct ResultLocPeer {
36693670 ResultLoc base;
36703671
src/ir.cpp+39-28
......@@ -16395,45 +16395,56 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
1639516395 }
1639616396
1639716397 ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
16398 if (peer_parent != nullptr && peer_parent->resolved_type == nullptr && !peer_parent->skipped) {
16399 // Suspend the phi first so that it gets resumed last
16400 ira->resume_stack.add_one();
16401 for (size_t i = ira->resume_stack.length;;) {
16402 if (i <= 1) break;
16403 i -= 1;
16404 ira->resume_stack.items[i] = ira->resume_stack.items[i-1];
16398 if (peer_parent != nullptr && !peer_parent->skipped && !peer_parent->done_resuming) {
16399 if (peer_parent->resolved_type == nullptr) {
16400 IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peer_count);
16401 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
16402 ResultLocPeer *this_peer = &peer_parent->peers[i];
16403
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 }
1640516432 }
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
1640916438 for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
16410 ResultLocPeer *this_peer = &peer_parent->peers[i];
1641116439 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 }
1642616440 if (opposite_peer->base.implicit_elem_type != nullptr &&
1642716441 opposite_peer->base.implicit_elem_type->id != ZigTypeIdUnreachable)
1642816442 {
1642916443 ira->resume_stack.append(opposite_peer->suspend_pos);
1643016444 }
1643116445 }
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;
1643716448 return ira_resume(ira);
1643816449 }
1643916450