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:...@@ -34,4 +34,3 @@ Performance optimizations to look into:
34 * enum literals can use small strings34 * enum literals can use small strings
35 * string literals can use small strings35 * string literals can use small strings
36 * don't need the Sema coercion on condbr condition, it's done with result locations36 * 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 {...@@ -935,11 +935,11 @@ pub const Scope = struct {
935 break_count: usize = 0,935 break_count: usize = 0,
936 /// Tracks `break :foo bar` instructions so they can possibly be elided later if936 /// Tracks `break :foo bar` instructions so they can possibly be elided later if
937 /// the labeled block ends up not needing a result location pointer.937 /// 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) = .{},
939 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions939 /// Tracks `store_to_block_ptr` instructions that correspond to break instructions
940 /// so they can possibly be elided later if the labeled block ends up not needing940 /// so they can possibly be elided later if the labeled block ends up not needing
941 /// a result location pointer.941 /// 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
944 pub const Label = struct {944 pub const Label = struct {
945 token: ast.TokenIndex,945 token: ast.TokenIndex,
...@@ -1226,8 +1226,8 @@ pub const Scope = struct {...@@ -1226,8 +1226,8 @@ pub const Scope = struct {
1226 gz: *GenZir,1226 gz: *GenZir,
1227 break_block: zir.Inst.Index,1227 break_block: zir.Inst.Index,
1228 operand: zir.Inst.Ref,1228 operand: zir.Inst.Ref,
1229 ) !zir.Inst.Ref {1229 ) !zir.Inst.Index {
1230 return try gz.add(.{1230 return gz.addAsIndex(.{
1231 .tag = .@"break",1231 .tag = .@"break",
1232 .data = .{ .@"break" = .{1232 .data = .{ .@"break" = .{
1233 .block_inst = break_block,1233 .block_inst = break_block,
...@@ -1237,15 +1237,14 @@ pub const Scope = struct {...@@ -1237,15 +1237,14 @@ pub const Scope = struct {
1237 }1237 }
12381238
1239 pub fn addBreakVoid(1239 pub fn addBreakVoid(
1240 inner_gz: *GenZir,1240 gz: *GenZir,
1241 block_gz: *GenZir,
1242 break_block: zir.Inst.Index,1241 break_block: zir.Inst.Index,
1243 node_index: ast.Node.Index,1242 node_index: ast.Node.Index,
1244 ) !zir.Inst.Ref {1243 ) !zir.Inst.Index {
1245 return try inner_gz.add(.{1244 return gz.addAsIndex(.{
1246 .tag = .break_void_node,1245 .tag = .break_void_node,
1247 .data = .{ .break_void_node = .{1246 .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),
1249 .block_inst = break_block,1248 .block_inst = break_block,
1250 } },1249 } },
1251 });1250 });
...@@ -1339,6 +1338,10 @@ pub const Scope = struct {...@@ -1339,6 +1338,10 @@ pub const Scope = struct {
1339 }1338 }
13401339
1341 pub fn add(gz: *GenZir, inst: zir.Inst) !zir.Inst.Ref {1340 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 {
1342 const gpa = gz.zir_code.gpa;1345 const gpa = gz.zir_code.gpa;
1343 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);1346 try gz.instructions.ensureCapacity(gpa, gz.instructions.items.len + 1);
1344 try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);1347 try gz.zir_code.instructions.ensureCapacity(gpa, gz.zir_code.instructions.len + 1);
...@@ -1346,7 +1349,7 @@ pub const Scope = struct {...@@ -1346,7 +1349,7 @@ pub const Scope = struct {
1346 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);1349 const new_index = @intCast(zir.Inst.Index, gz.zir_code.instructions.len);
1347 gz.zir_code.instructions.appendAssumeCapacity(inst);1350 gz.zir_code.instructions.appendAssumeCapacity(inst);
1348 gz.instructions.appendAssumeCapacity(new_index);1351 gz.instructions.appendAssumeCapacity(new_index);
1349 return gz.zir_code.indexToRef(new_index);1352 return new_index;
1350 }1353 }
1351 };1354 };
13521355
src/astgen.zig+32-42
...@@ -411,13 +411,16 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In...@@ -411,13 +411,16 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
411 return callExpr(mod, scope, rl, node, tree.callFull(node));411 return callExpr(mod, scope, rl, node, tree.callFull(node));
412 },412 },
413413
414 .unreachable_literal => return gz.add(.{414 .unreachable_literal => {
415 .tag = .@"unreachable",415 _ = try gz.addAsIndex(.{
416 .data = .{ .@"unreachable" = .{416 .tag = .@"unreachable",
417 .safety = true,417 .data = .{ .@"unreachable" = .{
418 .src_node = gz.zir_code.decl.nodeIndexToRelative(node),418 .safety = true,
419 } },419 .src_node = gz.zir_code.decl.nodeIndexToRelative(node),
420 }),420 } },
421 });
422 return zir.Inst.Ref.unreachable_value;
423 },
421 .@"return" => return ret(mod, scope, node),424 .@"return" => return ret(mod, scope, node),
422 .field_access => return fieldAccess(mod, scope, rl, node),425 .field_access => return fieldAccess(mod, scope, rl, node),
423 .float_literal => return floatLiteral(mod, scope, rl, node),426 .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...@@ -602,8 +605,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
602 .tagged_union_enum_tag_trailing,605 .tagged_union_enum_tag_trailing,
603 => return containerDecl(mod, scope, rl, tree.taggedUnionEnumTag(node)),606 => return containerDecl(mod, scope, rl, tree.taggedUnionEnumTag(node)),
604607
605 .@"break" => return breakExpr(mod, scope, rl, node),608 .@"break" => return breakExpr(mod, scope, node),
606 .@"continue" => return continueExpr(mod, scope, rl, node),609 .@"continue" => return continueExpr(mod, scope, node),
607 .grouped_expression => return expr(mod, scope, rl, node_datas[node].lhs),610 .grouped_expression => return expr(mod, scope, rl, node_datas[node].lhs),
608 .array_type => return arrayType(mod, scope, rl, node),611 .array_type => return arrayType(mod, scope, rl, node),
609 .array_type_sentinel => return arrayTypeSentinel(mod, scope, rl, node),612 .array_type_sentinel => return arrayTypeSentinel(mod, scope, rl, node),
...@@ -666,28 +669,19 @@ pub fn comptimeExpr(...@@ -666,28 +669,19 @@ pub fn comptimeExpr(
666 return result;669 return result;
667}670}
668671
669fn breakExpr(672fn breakExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
670 mod: *Module,673 const parent_gz = parent_scope.getGenZir();
671 parent_scope: *Scope,674 const tree = parent_gz.tree();
672 rl: ResultLoc,
673 node: ast.Node.Index,
674) InnerError!zir.Inst.Ref {
675 const tree = parent_scope.tree();
676 const node_datas = tree.nodes.items(.data);675 const node_datas = tree.nodes.items(.data);
677 const main_tokens = tree.nodes.items(.main_token);
678
679 const break_token = main_tokens[node];
680 const break_label = node_datas[node].lhs;676 const break_label = node_datas[node].lhs;
681 const rhs = node_datas[node].rhs;677 const rhs = node_datas[node].rhs;
682678
683 const parent_gz = parent_scope.getGenZir();
684
685 // Look for the label in the scope.679 // Look for the label in the scope.
686 var scope = parent_scope;680 var scope = parent_scope;
687 while (true) {681 while (true) {
688 switch (scope.tag) {682 switch (scope.tag) {
689 .gen_zir => {683 .gen_zir => {
690 const block_gz = scope.getGenZir();684 const block_gz = scope.cast(Scope.GenZir).?;
691685
692 const block_inst = blk: {686 const block_inst = blk: {
693 if (break_label != 0) {687 if (break_label != 0) {
...@@ -705,8 +699,8 @@ fn breakExpr(...@@ -705,8 +699,8 @@ fn breakExpr(
705 };699 };
706700
707 if (rhs == 0) {701 if (rhs == 0) {
708 const result = try parent_gz.addBreakVoid(block_gz, block_inst, node);702 _ = try parent_gz.addBreakVoid(block_inst, node);
709 return rvalue(mod, parent_scope, rl, result, node);703 return zir.Inst.Ref.unreachable_value;
710 }704 }
711 block_gz.break_count += 1;705 block_gz.break_count += 1;
712 const prev_rvalue_rl_count = block_gz.rvalue_rl_count;706 const prev_rvalue_rl_count = block_gz.rvalue_rl_count;
...@@ -721,13 +715,13 @@ fn breakExpr(...@@ -721,13 +715,13 @@ fn breakExpr(
721 if (have_store_to_block) {715 if (have_store_to_block) {
722 const zir_tags = parent_gz.zir_code.instructions.items(.tag);716 const zir_tags = parent_gz.zir_code.instructions.items(.tag);
723 const zir_datas = parent_gz.zir_code.instructions.items(.data);717 const zir_datas = parent_gz.zir_code.instructions.items(.data);
724 const last_inst = zir_tags.len - 2;718 const store_inst = @intCast(u32, zir_tags.len - 2);
725 assert(zir_tags[last_inst] == .store_to_block_ptr);719 assert(zir_tags[store_inst] == .store_to_block_ptr);
726 assert(zir_datas[last_inst].bin.lhs == block_gz.rl_ptr);720 assert(zir_datas[store_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));721 try block_gz.labeled_store_to_block_ptr_list.append(mod.gpa, store_inst);
728 }722 }
729 }723 }
730 return rvalue(mod, parent_scope, rl, br, node);724 return zir.Inst.Ref.unreachable_value;
731 },725 },
732 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,726 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
733 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,727 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
...@@ -735,18 +729,13 @@ fn breakExpr(...@@ -735,18 +729,13 @@ fn breakExpr(
735 const label_name = try mod.identifierTokenString(parent_scope, break_label);729 const label_name = try mod.identifierTokenString(parent_scope, break_label);
736 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});730 return mod.failTok(parent_scope, break_label, "label not found: '{s}'", .{label_name});
737 } else {731 } else {
738 return mod.failTok(parent_scope, break_token, "break expression outside loop", .{});732 return mod.failNode(parent_scope, node, "break expression outside loop", .{});
739 },733 },
740 }734 }
741 }735 }
742}736}
743737
744fn continueExpr(738fn continueExpr(mod: *Module, parent_scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Ref {
745 mod: *Module,
746 parent_scope: *Scope,
747 rl: ResultLoc,
748 node: ast.Node.Index,
749) InnerError!zir.Inst.Ref {
750 if (true) @panic("TODO update for zir-memory-layout");739 if (true) @panic("TODO update for zir-memory-layout");
751 const tree = parent_scope.tree();740 const tree = parent_scope.tree();
752 const node_datas = tree.nodes.items(.data);741 const node_datas = tree.nodes.items(.data);
...@@ -776,10 +765,10 @@ fn continueExpr(...@@ -776,10 +765,10 @@ fn continueExpr(
776 continue;765 continue;
777 }766 }
778767
779 const result = try addZirInstTag(mod, parent_scope, src, .break_void, .{768 _ = try addZirInstTag(mod, parent_scope, src, .break_void, .{
780 .block = continue_block,769 .block = continue_block,
781 });770 });
782 return rvalue(mod, parent_scope, rl, result);771 return zir.Inst.Ref.unreachable_value;
783 },772 },
784 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,773 .local_val => scope = scope.cast(Scope.LocalVal).?.parent,
785 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,774 .local_ptr => scope = scope.cast(Scope.LocalPtr).?.parent,
...@@ -1769,11 +1758,11 @@ fn finishThenElseBlock(...@@ -1769,11 +1758,11 @@ fn finishThenElseBlock(
1769 switch (strat.tag) {1758 switch (strat.tag) {
1770 .break_void => {1759 .break_void => {
1771 if (!wzc.refIsNoReturn(then_result)) {1760 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);
1773 }1762 }
1774 const elide_else = if (else_result != .none) wzc.refIsNoReturn(else_result) else false;1763 const elide_else = if (else_result != .none) wzc.refIsNoReturn(else_result) else false;
1775 if (!elide_else) {1764 if (!elide_else) {
1776 _ = try else_scope.addBreakVoid(block_scope, main_block, else_src);1765 _ = try else_scope.addBreakVoid(main_block, else_src);
1777 }1766 }
1778 assert(!strat.elide_store_to_block_ptr_instructions);1767 assert(!strat.elide_store_to_block_ptr_instructions);
1779 try setCondBrPayload(condbr, cond, then_scope, else_scope);1768 try setCondBrPayload(condbr, cond, then_scope, else_scope);
...@@ -1788,7 +1777,7 @@ fn finishThenElseBlock(...@@ -1788,7 +1777,7 @@ fn finishThenElseBlock(
1788 _ = try else_scope.addBreak(main_block, else_result);1777 _ = try else_scope.addBreak(main_block, else_result);
1789 }1778 }
1790 } else {1779 } else {
1791 _ = try else_scope.addBreakVoid(block_scope, main_block, else_src);1780 _ = try else_scope.addBreakVoid(main_block, else_src);
1792 }1781 }
1793 if (strat.elide_store_to_block_ptr_instructions) {1782 if (strat.elide_store_to_block_ptr_instructions) {
1794 try setCondBrPayloadElideBlockStorePtr(condbr, cond, then_scope, else_scope);1783 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...@@ -2799,7 +2788,8 @@ fn ret(mod: *Module, scope: *Scope, node: ast.Node.Index) InnerError!zir.Inst.Re
2799 };2788 };
2800 break :operand try expr(mod, scope, rl, operand_node);2789 break :operand try expr(mod, scope, rl, operand_node);
2801 } else .void_value;2790 } 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;
2803}2793}
28042794
2805fn identifier(2795fn identifier(