authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-24 20:45:14-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-24 20:45:14-07:00
log01bfd835bb9613d21f09c0c4f5b905b077b3d5f9
tree89a9fe2ca68d2055abebee9f17b2136f8e5997cf
parentea42ab34abc0408b66ce2c0212afd4f5705e8d43

stage2: clean up break / noreturn astgen

* Module.addBreak and addBreakVoid return zir.Inst.Index not Ref because Index is the simpler type and we never need a Ref for these. * astgen: make noreturn stuff return the unreachable_value and avoid unnecessary calls to rvalue() * breakExpr: avoid unnecessary access into the tokens array * breakExpr: fix incorrect `@intCast` (previously this unsafely casted an Index to a Ref)

3 files changed, 45 insertions(+), 53 deletions(-)

BRANCH_TODO-1
......@@ -34,4 +34,3 @@ Performance optimizations to look into:
3434 * enum literals can use small strings
3535 * string literals can use small strings
3636 * don't need the Sema coercion on condbr condition, it's done with result locations
37 * remove unreachable_value
src/Module.zig+13-10
......@@ -935,11 +935,11 @@ pub const Scope = struct {
935935 break_count: usize = 0,
936936 /// Tracks `break :foo bar` instructions so they can possibly be elided later if
937937 /// the labeled block ends up not needing a result location pointer.
938 labeled_breaks: std.ArrayListUnmanaged(zir.Inst.Ref) = .{},
938 labeled_breaks: std.ArrayListUnmanaged(zir.Inst.Index) = .{},
939939 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions
940940 /// so they can possibly be elided later if the labeled block ends up not needing
941941 /// a result location pointer.
942 labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(zir.Inst.Ref) = .{},
942 labeled_store_to_block_ptr_list: std.ArrayListUnmanaged(zir.Inst.Index) = .{},
943943
944944 pub const Label = struct {
945945 token: ast.TokenIndex,
......@@ -1226,8 +1226,8 @@ pub const Scope = struct {
12261226 gz: *GenZir,
12271227 break_block: zir.Inst.Index,
12281228 operand: zir.Inst.Ref,
1229 ) !zir.Inst.Ref {
1230 return try gz.add(.{
1229 ) !zir.Inst.Index {
1230 return gz.addAsIndex(.{
12311231 .tag = .@"break",
12321232 .data = .{ .@"break" = .{
12331233 .block_inst = break_block,
......@@ -1237,15 +1237,14 @@ pub const Scope = struct {
12371237 }
12381238
12391239 pub fn addBreakVoid(
1240 inner_gz: *GenZir,
1241 block_gz: *GenZir,
1240 gz: *GenZir,
12421241 break_block: zir.Inst.Index,
12431242 node_index: ast.Node.Index,
1244 ) !zir.Inst.Ref {
1245 return try inner_gz.add(.{
1243 ) !zir.Inst.Index {
1244 return gz.addAsIndex(.{
12461245 .tag = .break_void_node,
12471246 .data = .{ .break_void_node = .{
1248 .src_node = block_gz.zir_code.decl.nodeIndexToRelative(node_index),
1247 .src_node = gz.zir_code.decl.nodeIndexToRelative(node_index),
12491248 .block_inst = break_block,
12501249 } },
12511250 });
......@@ -1339,6 +1338,10 @@ pub const Scope = struct {
13391338 }
13401339
13411340 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {
1341 return gz.zir_code.indexToRef(try gz.addAsIndex(inst));
1342 }
1343
1344 pub fn addAsIndex(gz: *GenZir, inst: zir.Inst) !zir.Inst.Index {
13421345 const gpa = gz.zir_code.gpa;
13431346 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
13441347 try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
......@@ -1346,7 +1349,7 @@ pub const Scope = struct {
13461349 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
13471350 gz.zir_code.instructions.appendAssumeCapacity(inst);
13481351 gz.instructions.appendAssumeCapacity(new_index);
1349 return gz.zir_code.indexToRef(new_index);
1352 return new_index;
13501353 }
13511354 };
13521355
src/astgen.zig+32-42
......@@ -411,13 +411,16 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
411411 return callExpr(mod, scope, rl, node, tree.callFull(node));
412412 },
413413
414 .unreachable_literal => return gz.add(.{
415 .tag = .@"unreachable",
416 .data = .{ .@"unreachable" = .{
417 .safety = true,
418 .src_node = gz.zir_code.decl.nodeIndexToRelative(node),
419 } },
420 }),
414 .unreachable_literal => {
415 _ = try gz.addAsIndex(.{
416 .tag = .@"unreachable",
417 .data = .{ .@"unreachable" = .{
418 .safety = true,
419 .src_node = gz.zir_code.decl.nodeIndexToRelative(node),
420 } },
421 });
422 return zir.Inst.Ref.unreachable_value;
423 },
421424 .@"return" => return ret(mod, scope, node),
422425 .field_access => return fieldAccess(mod, scope, rl, node),
423426 .float_literal => return floatLiteral(mod, scope, rl, node),
......@@ -602,8 +605,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
602605 .tagged_union_enum_tag_trailing,
603606 => return containerDecl(mod, scope, rl, tree.taggedUnionEnumTag(node)),
604607
605 .@"break" => return breakExpr(mod, scope, rl, node),
606 .@"continue" => return continueExpr(mod, scope, rl, node),
608 .@"break" => return breakExpr(mod, scope, node),
609 .@"continue" => return continueExpr(mod, scope, node),
607610 .grouped_expression => return expr(mod, scope, rl, node_datas[node].lhs),
608611 .array_type => return arrayType(mod, scope, rl, node),
609612 .array_type_sentinel => return arrayTypeSentinel(mod, scope, rl, node),
......@@ -666,28 +669,19 @@ pub fn comptimeExpr(
666669 return result;
667670}
668671
669fn breakExpr(
670 mod: *Module,
671 parent_scope: *Scope,
672 rl: ResultLoc,
673 node: ast.Node.Index,
674) InnerError!zir.Inst.Ref {
675 const tree = parent_scope.tree();
672fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
673 const parent_gz = parent_scope.getGenZir();
674 const tree = parent_gz.tree();
676675 const node_datas = tree.nodes.items(.data);
677 const main_tokens = tree.nodes.items(.main_token);
678
679 const break_token = main_tokens[node];
680676 const break_label = node_datas[node].lhs;
681677 const rhs = node_datas[node].rhs;
682678
683 const parent_gz = parent_scope.getGenZir();
684
685679 // Look for the label in the scope.
686680 var scope = parent_scope;
687681 while (true) {
688682 switch (scope.tag) {
689683 .gen_zir => {
690 const block_gz = scope.getGenZir();
684 const block_gz = scope.cast(Scope.GenZir).?;
691685
692686 const block_inst = blk: {
693687 if (break_label != 0) {
......@@ -705,8 +699,8 @@ fn breakExpr(
705699 };
706700
707701 if (rhs == 0) {
708 const result = try parent_gz.addBreakVoid(block_gz, block_inst, node);
709 return rvalue(mod, parent_scope, rl, result, node);
702 _ = try parent_gz.addBreakVoid(block_inst, node);
703 return zir.Inst.Ref.unreachable_value;
710704 }
711705 block_gz.break_count += 1;
712706 const prev_rvalue_rl_count = block_gz.rvalue_rl_count;
......@@ -721,13 +715,13 @@ fn breakExpr(
721715 if (have_store_to_block) {
722716 const zir_tags = parent_gz.zir_code.instructions.items(.tag);
723717 const zir_datas = parent_gz.zir_code.instructions.items(.data);
724 const last_inst = zir_tags.len - 2;
725 assert(zir_tags[last_inst] == .store_to_block_ptr);
726 assert(zir_datas[last_inst].bin.lhs == block_gz.rl_ptr);
727 try block_gz.labeled_store_to_block_ptr_list.append(mod.gpa, @intCast(zir.Inst.Ref, last_inst));
718 const store_inst = @intCast(u32, zir_tags.len - 2);
719 assert(zir_tags[store_inst] == .store_to_block_ptr);
720 assert(zir_datas[store_inst].bin.lhs == block_gz.rl_ptr);
721 try block_gz.labeled_store_to_block_ptr_list.append(mod.gpa, store_inst);
728722 }
729723 }
730 return rvalue(mod, parent_scope, rl, br, node);
724 return zir.Inst.Ref.unreachable_value;
731725 },
732726 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
733727 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
......@@ -735,18 +729,13 @@ fn breakExpr(
735729 const label_name = try mod.identifierTokenString(parent_scope, break_label);
736730 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
737731 } else {
738 return mod.failTok(parent_scope, break_token, "break expression outside loop", .{});
732 return mod.failNode(parent_scope, node, "break expression outside loop", .{});
739733 },
740734 }
741735 }
742736}
743737
744fn continueExpr(
745 mod: *Module,
746 parent_scope: *Scope,
747 rl: ResultLoc,
748 node: ast.Node.Index,
749) InnerError!zir.Inst.Ref {
738fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
750739 if (true) @panic("TODO update for zir-memory-layout");
751740 const tree = parent_scope.tree();
752741 const node_datas = tree.nodes.items(.data);
......@@ -776,10 +765,10 @@ fn continueExpr(
776765 continue;
777766 }
778767
779 const result = try addZirInstTag(mod, parent_scope, src, .break_void, .{
768 _ = try addZirInstTag(mod, parent_scope, src, .break_void, .{
780769 .block = continue_block,
781770 });
782 return rvalue(mod, parent_scope, rl, result);
771 return zir.Inst.Ref.unreachable_value;
783772 },
784773 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
785774 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
......@@ -1769,11 +1758,11 @@ fn finishThenElseBlock(
17691758 switch (strat.tag) {
17701759 .break_void => {
17711760 if (!wzc.refIsNoReturn(then_result)) {
1772 _ = try then_scope.addBreakVoid(block_scope, then_break_block, then_src);
1761 _ = try then_scope.addBreakVoid(then_break_block, then_src);
17731762 }
17741763 const elide_else = if (else_result != .none) wzc.refIsNoReturn(else_result) else false;
17751764 if (!elide_else) {
1776 _ = try else_scope.addBreakVoid(block_scope, main_block, else_src);
1765 _ = try else_scope.addBreakVoid(main_block, else_src);
17771766 }
17781767 assert(!strat.elide_store_to_block_ptr_instructions);
17791768 try setCondBrPayload(condbr, cond, then_scope, else_scope);
......@@ -1788,7 +1777,7 @@ fn finishThenElseBlock(
17881777 _ = try else_scope.addBreak(main_block, else_result);
17891778 }
17901779 } else {
1791 _ = try else_scope.addBreakVoid(block_scope, main_block, else_src);
1780 _ = try else_scope.addBreakVoid(main_block, else_src);
17921781 }
17931782 if (strat.elide_store_to_block_ptr_instructions) {
17941783 try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope);
......@@ -2799,7 +2788,8 @@ fn ret(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Re
27992788 };
28002789 break :operand try expr(mod, scope, rl, operand_node);
28012790 } else .void_value;
2802 return gz.addUnNode(.ret_node, operand, node);
2791 _ = try gz.addUnNode(.ret_node, operand, node);
2792 return zir.Inst.Ref.unreachable_value;
28032793}
28042794
28052795fn identifier(