From a97e5e119afb80e0d6d047682b8301bab9423078 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 19 Jul 2021 18:58:51 -0700 Subject: [PATCH] stage2: switch: fix Sema bugs and implement AIR printing --- src/Liveness.zig | 10 +++++----- src/Sema.zig | 9 ++++++--- src/print_air.zig | 47 +++++++++++++++++++++++++++++------------------ 3 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/Liveness.zig b/src/Liveness.zig index 2c226122bf..02d0ea7bc5 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -442,9 +442,9 @@ fn analyzeInst( return trackOperands(a, new_set, inst, main_tomb, .{ condition, .none, .none }); }, .switch_br => { - const inst_data = inst_datas[inst].pl_op; - const condition = inst_data.operand; - const switch_br = a.air.extraData(Air.SwitchBr, inst_data.payload); + const pl_op = inst_datas[inst].pl_op; + const condition = pl_op.operand; + const switch_br = a.air.extraData(Air.SwitchBr, pl_op.payload); const Table = std.AutoHashMapUnmanaged(Air.Inst.Index, void); const case_tables = try gpa.alloc(Table, switch_br.data.cases_len + 1); // +1 for else @@ -456,8 +456,8 @@ fn analyzeInst( var air_extra_index: usize = switch_br.end; for (case_tables[0..switch_br.data.cases_len]) |*case_table| { const case = a.air.extraData(Air.SwitchBr.Case, air_extra_index); - const case_body = a.air.extra[case.end..][0..case.data.body_len]; - air_extra_index = case.end + case_body.len; + const case_body = a.air.extra[case.end + case.data.items_len ..][0..case.data.body_len]; + air_extra_index = case.end + case.data.items_len + case_body.len; try analyzeWithContext(a, case_table, case_body); // Reset the table back to its state from before the case. diff --git a/src/Sema.zig b/src/Sema.zig index b9449157e2..826097c3d1 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -4213,6 +4213,7 @@ fn analyzeSwitch( var prev_then_body: []const Air.Inst.Index = &.{}; defer gpa.free(prev_then_body); + var cases_len = scalar_cases_len; var multi_i: usize = 0; while (multi_i < multi_cases_len) : (multi_i += 1) { const items_len = sema.code.extra[extra_index]; @@ -4232,6 +4233,8 @@ fn analyzeSwitch( // else prong. Otherwise, we can take advantage of multiple items // mapping to the same body. if (ranges_len == 0) { + cases_len += 1; + const body = sema.code.extra[extra_index..][0..body_len]; extra_index += body_len; _ = try sema.analyzeBody(&case_block, body); @@ -4239,7 +4242,7 @@ fn analyzeSwitch( try cases_extra.ensureUnusedCapacity(gpa, 2 + items.len + case_block.instructions.items.len); - cases_extra.appendAssumeCapacity(1); // items_len + cases_extra.appendAssumeCapacity(@intCast(u32, items.len)); cases_extra.appendAssumeCapacity(@intCast(u32, case_block.instructions.items.len)); for (items) |item_ref| { @@ -4352,12 +4355,12 @@ fn analyzeSwitch( } try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.SwitchBr).Struct.fields.len + - cases_extra.items.len); + cases_extra.items.len + final_else_body.len); _ = try child_block.addInst(.{ .tag = .switch_br, .data = .{ .pl_op = .{ .operand = operand, .payload = sema.addExtraAssumeCapacity(Air.SwitchBr{ - .cases_len = @intCast(u32, scalar_cases_len + multi_cases_len), + .cases_len = @intCast(u32, cases_len), .else_body_len = @intCast(u32, final_else_body.len), }), } } }); diff --git a/src/print_air.zig b/src/print_air.zig index f31b307b57..51f0ce4f49 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -300,33 +300,44 @@ const Writer = struct { fn writeSwitchBr(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { const pl_op = w.air.instructions.items(.data)[inst].pl_op; - const extra = w.air.extraData(Air.SwitchBr, pl_op.payload); - const cases = w.air.extra[extra.end..][0..extra.data.cases_len]; - const else_body = w.air.extra[extra.end + cases.len ..][0..extra.data.else_body_len]; + const switch_br = w.air.extraData(Air.SwitchBr, pl_op.payload); + var extra_index: usize = switch_br.end; + var case_i: u32 = 0; try w.writeInstRef(s, pl_op.operand); - try s.writeAll(", {\n"); - const old_indent = w.indent; - if (else_body.len != 0) { - w.indent += 2; - try w.writeBody(s, else_body); - try s.writeByteNTimes(' ', old_indent); - try s.writeAll("}, {\n"); - w.indent = old_indent; - } + w.indent += 2; - for (cases) |case_index| { - const case = w.air.extraData(Air.SwitchBr.Case, case_index); - const case_body = w.air.extra[case.end..][0..case.data.body_len]; + while (case_i < switch_br.data.cases_len) : (case_i += 1) { + const case = w.air.extraData(Air.SwitchBr.Case, extra_index); + const items = @bitCast([]const Air.Inst.Ref, w.air.extra[case.end..][0..case.data.items_len]); + const case_body = w.air.extra[case.end + items.len ..][0..case.data.body_len]; + extra_index = case.end + case.data.items_len + case_body.len; + try s.writeAll(", ["); + for (items) |item, item_i| { + if (item_i != 0) try s.writeAll(", "); + try w.writeInstRef(s, item); + } + try s.writeAll("] => {\n"); w.indent += 2; try w.writeBody(s, case_body); - try s.writeByteNTimes(' ', old_indent); - try s.writeAll("}, {\n"); - w.indent = old_indent; + w.indent -= 2; + try s.writeByteNTimes(' ', w.indent); + try s.writeAll("}"); } + const else_body = w.air.extra[extra_index..][0..switch_br.data.else_body_len]; + if (else_body.len != 0) { + try s.writeAll(", else => {\n"); + w.indent += 2; + try w.writeBody(s, else_body); + w.indent -= 2; + try s.writeByteNTimes(' ', w.indent); + try s.writeAll("}"); + } + + try s.writeAll("\n"); try s.writeByteNTimes(' ', old_indent); try s.writeAll("}"); }