fix nested peer result locs with no memory loc

```zig
export fn entry2(c: bool) i32 {
    return if (c)
        i32(0)
    else if (c)
        i32(1)
    else
        i32(2);
}
```

```llvm
define i32 @entry2(i1) #2 !dbg !35 {
Entry:
  %c = alloca i1, align 1
  store i1 %0, i1* %c, align 1
  call void @llvm.dbg.declare(metadata i1* %c, metadata !41, metadata !DIExpression()), !dbg !42
  %1 = load i1, i1* %c, align 1, !dbg !43
  br i1 %1, label %Then, label %Else, !dbg !43

Then:                                             ; preds = %Entry
  br label %EndIf3, !dbg !45

Else:                                             ; preds = %Entry
  %2 = load i1, i1* %c, align 1, !dbg !46
  br i1 %2, label %Then1, label %Else2, !dbg !46

Then1:                                            ; preds = %Else
  br label %EndIf, !dbg !47

Else2:                                            ; preds = %Else
  br label %EndIf, !dbg !47

EndIf:                                            ; preds = %Else2, %Then1
  %3 = phi i32 [ 1, %Then1 ], [ 2, %Else2 ], !dbg !47
  br label %EndIf3, !dbg !45

EndIf3:                                           ; preds = %EndIf, %Then
  %4 = phi i32 [ 0, %Then ], [ %3, %EndIf ], !dbg !45
  ret i32 %4, !dbg !48
}
```
This commit is contained in:
Andrew Kelley 2019-06-12 18:08:56 -04:00
parent 1526d89711
commit e6fa2ee706
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 17 additions and 11 deletions

View File

@ -3652,6 +3652,7 @@ struct ResultLocReturn {
struct ResultLocPeerParent {
ResultLoc base;
bool skipped;
ResultLoc *parent;
ResultLocPeer *peers;
size_t peer_count;

View File

@ -14899,7 +14899,10 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
bool is_comptime;
if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime))
return ira->codegen->invalid_instruction;
if (is_comptime) return nullptr;
peer_parent->skipped = is_comptime;
if (peer_parent->skipped) {
return nullptr;
}
if (peer_parent->resolved_type == nullptr) {
ResultLocPeer *last_peer = &peer_parent->peers[peer_parent->peer_count - 1];
@ -14916,6 +14919,7 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
{
return parent_result_loc;
}
result_loc->written = true;
result_loc->resolved_loc = parent_result_loc;
return result_loc->resolved_loc;
}
@ -16385,16 +16389,15 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
}
ResultLocPeerParent *peer_parent = phi_instruction->peer_parent;
if (peer_parent != nullptr && peer_parent->resolved_type == nullptr) {
bool is_comptime;
if (!ir_resolve_comptime(ira, peer_parent->is_comptime->child, &is_comptime))
return ira->codegen->invalid_instruction;
if (is_comptime) goto skip_peer_stuff;
if (peer_parent != nullptr && peer_parent->resolved_type == nullptr && !peer_parent->skipped) {
// Suspend the phi first so that it gets resumed last
IrSuspendPosition suspend_pos;
ira_suspend(ira, &phi_instruction->base, nullptr, &suspend_pos);
ira->resume_stack.append(suspend_pos);
ira->resume_stack.add_one();
for (size_t i = ira->resume_stack.length;;) {
if (i <= 1) break;
i -= 1;
ira->resume_stack.items[i] = ira->resume_stack.items[i-1];
}
ira_suspend(ira, &phi_instruction->base, nullptr, &ira->resume_stack.items[0]);
IrInstruction **instructions = allocate<IrInstruction *>(peer_parent->peer_count);
for (size_t i = 0; i < peer_parent->peer_count; i += 1) {
@ -16427,7 +16430,6 @@ static IrInstruction *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionPh
return ira_resume(ira);
}
skip_peer_stuff:
ZigList<IrBasicBlock*> new_incoming_blocks = {0};
ZigList<IrInstruction*> new_incoming_values = {0};
@ -24598,6 +24600,9 @@ ZigType *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutable *new_
continue;
}
if (ira->codegen->verbose_ir) {
fprintf(stderr, "analyze #%zu\n", old_instruction->debug_id);
}
IrInstruction *new_instruction = ir_analyze_instruction_base(ira, old_instruction);
if (new_instruction != nullptr) {
ir_assert(new_instruction->value.type != nullptr || new_instruction->value.type != nullptr, old_instruction);