authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-13 15:27:29+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-13 15:27:29+03:00
logc5368ba20c79b62d658c71033df9aeb7aa6e4581
treed3497333bb4df3e52a473627a5a8b7666c6239df
parent373488157751dbaa22415ce842c4f5616fc845ff
signature Commit is signed but in an unrecognized format.

translate-c: ensure generated labels are unique


2 files changed, 81 insertions(+), 69 deletions(-)

src-self-hosted/translate_c.zig+68-56
......@@ -61,7 +61,8 @@ const Scope = struct {
6161 pending_block: Block,
6262 cases: []*ast.Node,
6363 case_index: usize,
64 has_default: bool = false,
64 switch_label: ?[]const u8,
65 default_label: ?[]const u8,
6566 };
6667
6768 /// Used for the scope of condition expressions, for example `if (cond)`.
......@@ -73,7 +74,7 @@ const Scope = struct {
7374
7475 fn getBlockScope(self: *Condition, c: *Context) !*Block {
7576 if (self.block) |*b| return b;
76 self.block = try Block.init(c, &self.base, "blk");
77 self.block = try Block.init(c, &self.base, true);
7778 return &self.block.?;
7879 }
7980
......@@ -93,21 +94,22 @@ const Scope = struct {
9394 mangle_count: u32 = 0,
9495 lbrace: ast.TokenIndex,
9596
96 fn init(c: *Context, parent: *Scope, label: ?[]const u8) !Block {
97 return Block{
97 fn init(c: *Context, parent: *Scope, labeled: bool) !Block {
98 var blk = Block{
9899 .base = .{
99100 .id = .Block,
100101 .parent = parent,
101102 },
102103 .statements = std.ArrayList(*ast.Node).init(c.gpa),
103104 .variables = AliasList.init(c.gpa),
104 .label = if (label) |l| blk: {
105 const ll = try appendIdentifier(c, l);
106 _ = try appendToken(c, .Colon, ":");
107 break :blk ll;
108 } else null,
105 .label = null,
109106 .lbrace = try appendToken(c, .LBrace, "{"),
110107 };
108 if (labeled) {
109 blk.label = try appendIdentifier(c, try blk.makeMangledName(c, "blk"));
110 _ = try appendToken(c, .Colon, ":");
111 }
112 return blk;
111113 }
112114
113115 fn deinit(self: *Block) void {
......@@ -577,7 +579,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
577579
578580 // actual function definition with body
579581 const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
580 var block_scope = try Scope.Block.init(rp.c, &c.global_scope.base, null);
582 var block_scope = try Scope.Block.init(rp.c, &c.global_scope.base, false);
581583 defer block_scope.deinit();
582584 var scope = &block_scope.base;
583585
......@@ -1307,7 +1309,7 @@ fn transBinaryOperator(
13071309 const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
13081310 if (expr) {
13091311 _ = try appendToken(rp.c, .Semicolon, ";");
1310 const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, rhs);
1312 const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs);
13111313 try block_scope.statements.append(&break_node.base);
13121314 const block_node = try block_scope.complete(rp.c);
13131315 const rparen = try appendToken(rp.c, .RParen, ")");
......@@ -1476,7 +1478,7 @@ fn transCompoundStmtInline(
14761478}
14771479
14781480fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
1479 var block_scope = try Scope.Block.init(rp.c, scope, null);
1481 var block_scope = try Scope.Block.init(rp.c, scope, false);
14801482 defer block_scope.deinit();
14811483 try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope);
14821484 const node = try block_scope.complete(rp.c);
......@@ -2587,7 +2589,7 @@ fn transForLoop(
25872589 defer if (block_scope) |*bs| bs.deinit();
25882590
25892591 if (ZigClangForStmt_getInit(stmt)) |init| {
2590 block_scope = try Scope.Block.init(rp.c, scope, null);
2592 block_scope = try Scope.Block.init(rp.c, scope, false);
25912593 loop_scope.parent = &block_scope.?.base;
25922594 const init_node = try transStmt(rp, &block_scope.?.base, init, .unused, .r_value);
25932595 try block_scope.?.statements.append(init_node);
......@@ -2673,17 +2675,19 @@ fn transSwitch(
26732675 .cases = switch_node.cases(),
26742676 .case_index = 0,
26752677 .pending_block = undefined,
2678 .default_label = null,
2679 .switch_label = null,
26762680 };
26772681
26782682 // tmp block that all statements will go before being picked up by a case or default
2679 var block_scope = try Scope.Block.init(rp.c, &switch_scope.base, null);
2683 var block_scope = try Scope.Block.init(rp.c, &switch_scope.base, false);
26802684 defer block_scope.deinit();
26812685
26822686 // Note that we do not defer a deinit here; the switch_scope.pending_block field
26832687 // has its own memory management. This resource is freed inside `transCase` and
26842688 // then the final pending_block is freed at the bottom of this function with
26852689 // pending_block.deinit().
2686 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null);
2690 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
26872691 try switch_scope.pending_block.statements.append(&switch_node.base);
26882692
26892693 const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value);
......@@ -2698,11 +2702,19 @@ fn transSwitch(
26982702 switch_scope.pending_block.statements.appendAssumeCapacity(n);
26992703 }
27002704
2701 switch_scope.pending_block.label = try appendIdentifier(rp.c, "__switch");
2702 _ = try appendToken(rp.c, .Colon, ":");
2703 if (!switch_scope.has_default) {
2705 if (switch_scope.default_label == null) {
2706 switch_scope.switch_label = try block_scope.makeMangledName(rp.c, "switch");
2707 }
2708 if (switch_scope.switch_label) |l| {
2709 switch_scope.pending_block.label = try appendIdentifier(rp.c, l);
2710 _ = try appendToken(rp.c, .Colon, ":");
2711 }
2712 if (switch_scope.default_label == null) {
27042713 const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));
2705 else_prong.expr = &(try transCreateNodeBreak(rp.c, "__switch", null)).base;
2714 else_prong.expr = blk: {
2715 var br = try CtrlFlow.init(rp.c, .Break, switch_scope.switch_label.?);
2716 break :blk &(try br.finish(null)).base;
2717 };
27062718 _ = try appendToken(rp.c, .Comma, ",");
27072719
27082720 if (switch_scope.case_index >= switch_scope.cases.len)
......@@ -2726,7 +2738,7 @@ fn transCase(
27262738) TransError!*ast.Node {
27272739 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
27282740 const switch_scope = scope.getSwitch();
2729 const label = try std.fmt.allocPrint(rp.c.arena, "__case_{}", .{switch_scope.case_index - @boolToInt(switch_scope.has_default)});
2741 const label = try block_scope.makeMangledName(rp.c, "case");
27302742 _ = try appendToken(rp.c, .Semicolon, ";");
27312743
27322744 const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {
......@@ -2746,7 +2758,10 @@ fn transCase(
27462758 try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);
27472759
27482760 const switch_prong = try transCreateNodeSwitchCase(rp.c, expr);
2749 switch_prong.expr = &(try transCreateNodeBreak(rp.c, label, null)).base;
2761 switch_prong.expr = blk: {
2762 var br = try CtrlFlow.init(rp.c, .Break, label);
2763 break :blk &(try br.finish(null)).base;
2764 };
27502765 _ = try appendToken(rp.c, .Comma, ",");
27512766
27522767 if (switch_scope.case_index >= switch_scope.cases.len)
......@@ -2763,7 +2778,7 @@ fn transCase(
27632778
27642779 const pending_node = try switch_scope.pending_block.complete(rp.c);
27652780 switch_scope.pending_block.deinit();
2766 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null);
2781 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
27672782
27682783 try switch_scope.pending_block.statements.append(&pending_node.base);
27692784
......@@ -2777,12 +2792,14 @@ fn transDefault(
27772792) TransError!*ast.Node {
27782793 const block_scope = scope.findBlockScope(rp.c) catch unreachable;
27792794 const switch_scope = scope.getSwitch();
2780 const label = "__default";
2781 switch_scope.has_default = true;
2795 switch_scope.default_label = try block_scope.makeMangledName(rp.c, "default");
27822796 _ = try appendToken(rp.c, .Semicolon, ";");
27832797
27842798 const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));
2785 else_prong.expr = &(try transCreateNodeBreak(rp.c, label, null)).base;
2799 else_prong.expr = blk: {
2800 var br = try CtrlFlow.init(rp.c, .Break, switch_scope.default_label.?);
2801 break :blk &(try br.finish(null)).base;
2802 };
27862803 _ = try appendToken(rp.c, .Comma, ",");
27872804
27882805 if (switch_scope.case_index >= switch_scope.cases.len)
......@@ -2790,7 +2807,7 @@ fn transDefault(
27902807 switch_scope.cases[switch_scope.case_index] = &else_prong.base;
27912808 switch_scope.case_index += 1;
27922809
2793 switch_scope.pending_block.label = try appendIdentifier(rp.c, label);
2810 switch_scope.pending_block.label = try appendIdentifier(rp.c, switch_scope.default_label.?);
27942811 _ = try appendToken(rp.c, .Colon, ":");
27952812
27962813 // take all pending statements
......@@ -2799,7 +2816,7 @@ fn transDefault(
27992816
28002817 const pending_node = try switch_scope.pending_block.complete(rp.c);
28012818 switch_scope.pending_block.deinit();
2802 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null);
2819 switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
28032820 try switch_scope.pending_block.statements.append(&pending_node.base);
28042821
28052822 return transStmt(rp, scope, ZigClangDefaultStmt_getSubStmt(stmt), .unused, .r_value);
......@@ -2894,7 +2911,7 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr,
28942911 return transCompoundStmt(rp, scope, comp);
28952912 }
28962913 const lparen = try appendToken(rp.c, .LParen, "(");
2897 var block_scope = try Scope.Block.init(rp.c, scope, "blk");
2914 var block_scope = try Scope.Block.init(rp.c, scope, true);
28982915 defer block_scope.deinit();
28992916
29002917 var it = ZigClangCompoundStmt_body_begin(comp);
......@@ -3209,7 +3226,7 @@ fn transCreatePreCrement(
32093226 // zig: _ref.* += 1;
32103227 // zig: break :blk _ref.*
32113228 // zig: })
3212 var block_scope = try Scope.Block.init(rp.c, scope, "blk");
3229 var block_scope = try Scope.Block.init(rp.c, scope, true);
32133230 defer block_scope.deinit();
32143231 const ref = try block_scope.makeMangledName(rp.c, "ref");
32153232
......@@ -3239,7 +3256,7 @@ fn transCreatePreCrement(
32393256 const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false);
32403257 try block_scope.statements.append(assign);
32413258
3242 const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, ref_node);
3259 const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node);
32433260 try block_scope.statements.append(&break_node.base);
32443261 const block_node = try block_scope.complete(rp.c);
32453262 // semicolon must immediately follow rbrace because it is the last token in a block
......@@ -3283,7 +3300,7 @@ fn transCreatePostCrement(
32833300 // zig: _ref.* += 1;
32843301 // zig: break :blk _tmp
32853302 // zig: })
3286 var block_scope = try Scope.Block.init(rp.c, scope, "blk");
3303 var block_scope = try Scope.Block.init(rp.c, scope, true);
32873304 defer block_scope.deinit();
32883305 const ref = try block_scope.makeMangledName(rp.c, "ref");
32893306
......@@ -3458,7 +3475,7 @@ fn transCreateCompoundAssign(
34583475 // zig: _ref.* = _ref.* + rhs;
34593476 // zig: break :blk _ref.*
34603477 // zig: })
3461 var block_scope = try Scope.Block.init(rp.c, scope, "blk");
3478 var block_scope = try Scope.Block.init(rp.c, scope, true);
34623479 defer block_scope.deinit();
34633480 const ref = try block_scope.makeMangledName(rp.c, "ref");
34643481
......@@ -3526,7 +3543,7 @@ fn transCreateCompoundAssign(
35263543 try block_scope.statements.append(assign);
35273544 }
35283545
3529 const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, ref_node);
3546 const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node);
35303547 try block_scope.statements.append(&break_node.base);
35313548 const block_node = try block_scope.complete(rp.c);
35323549 const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
......@@ -3602,8 +3619,16 @@ fn transCPtrCast(
36023619
36033620fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {
36043621 const break_scope = scope.getBreakableScope();
3605 const label_text: ?[]const u8 = if (break_scope.id == .Switch) "__switch" else null;
3606 const br = try transCreateNodeBreak(rp.c, label_text, null);
3622 const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: {
3623 const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope);
3624 const block_scope = try scope.findBlockScope(rp.c);
3625 swtch.switch_label = try block_scope.makeMangledName(rp.c, "switch");
3626 break :blk swtch.switch_label;
3627 } else
3628 null;
3629
3630 var cf = try CtrlFlow.init(rp.c, .Break, label_text);
3631 const br = try cf.finish(null);
36073632 _ = try appendToken(rp.c, .Semicolon, ";");
36083633 return &br.base;
36093634}
......@@ -3634,7 +3659,7 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const
36343659 // })
36353660 const lparen = try appendToken(rp.c, .LParen, "(");
36363661
3637 var block_scope = try Scope.Block.init(rp.c, scope, "blk");
3662 var block_scope = try Scope.Block.init(rp.c, scope, true);
36383663 defer block_scope.deinit();
36393664
36403665 const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp");
......@@ -4082,8 +4107,7 @@ fn transCreateNodeAssign(
40824107 // zig: lhs = _tmp;
40834108 // zig: break :blk _tmp
40844109 // zig: })
4085 const label_name = "blk";
4086 var block_scope = try Scope.Block.init(rp.c, scope, label_name);
4110 var block_scope = try Scope.Block.init(rp.c, scope, true);
40874111 defer block_scope.deinit();
40884112
40894113 const tmp = try block_scope.makeMangledName(rp.c, "tmp");
......@@ -4118,7 +4142,7 @@ fn transCreateNodeAssign(
41184142 try block_scope.statements.append(assign);
41194143
41204144 const break_node = blk: {
4121 var tmp_ctrl_flow = try CtrlFlow.init(rp.c, .Break, label_name);
4145 var tmp_ctrl_flow = try CtrlFlow.init(rp.c, .Break, tokenSlice(rp.c, block_scope.label.?));
41224146 const rhs_expr = try transCreateNodeIdentifier(rp.c, tmp);
41234147 break :blk try tmp_ctrl_flow.finish(rhs_expr);
41244148 };
......@@ -4495,23 +4519,12 @@ fn transCreateNodeElse(c: *Context) !*ast.Node.Else {
44954519 return node;
44964520}
44974521
4498fn transCreateNodeBreakToken(
4499 c: *Context,
4500 label: ?ast.TokenIndex,
4501 rhs: ?*ast.Node,
4502) !*ast.Node.ControlFlowExpression {
4503 const other_token = label orelse return transCreateNodeBreak(c, null, rhs);
4504 const loc = c.token_locs.items[other_token];
4505 const label_name = c.source_buffer.items[loc.start..loc.end];
4506 return transCreateNodeBreak(c, label_name, rhs);
4507}
4508
45094522fn transCreateNodeBreak(
45104523 c: *Context,
4511 label: ?[]const u8,
4524 label: ?ast.TokenIndex,
45124525 rhs: ?*ast.Node,
45134526) !*ast.Node.ControlFlowExpression {
4514 var ctrl_flow = try CtrlFlow.init(c, .Break, label);
4527 var ctrl_flow = try CtrlFlow.init(c, .Break, if (label) |l| tokenSlice(c, l) else null);
45154528 return ctrl_flow.finish(rhs);
45164529}
45174530
......@@ -5362,7 +5375,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
53625375}
53635376
53645377fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
5365 var block_scope = try Scope.Block.init(c, &c.global_scope.base, null);
5378 var block_scope = try Scope.Block.init(c, &c.global_scope.base, false);
53665379 defer block_scope.deinit();
53675380 const scope = &block_scope.base;
53685381
......@@ -5475,8 +5488,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
54755488 },
54765489 .Comma => {
54775490 _ = try appendToken(c, .Semicolon, ";");
5478 const label_name = "blk";
5479 var block_scope = try Scope.Block.init(c, scope, label_name);
5491 var block_scope = try Scope.Block.init(c, scope, true);
54805492 defer block_scope.deinit();
54815493
54825494 var last = node;
......@@ -5501,7 +5513,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
55015513 }
55025514 }
55035515
5504 const break_node = try transCreateNodeBreak(c, label_name, last);
5516 const break_node = try transCreateNodeBreak(c, block_scope.label, last);
55055517 try block_scope.statements.append(&break_node.base);
55065518 const block_node = try block_scope.complete(c);
55075519 return &block_node.base;
test/translate_c.zig+13-13
......@@ -1730,16 +1730,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17301730 \\pub export fn switch_fn(arg_i: c_int) c_int {
17311731 \\ var i = arg_i;
17321732 \\ var res: c_int = 0;
1733 \\ __switch: {
1734 \\ __case_2: {
1735 \\ __default: {
1736 \\ __case_1: {
1737 \\ __case_0: {
1733 \\ @"switch": {
1734 \\ case_2: {
1735 \\ default: {
1736 \\ case_1: {
1737 \\ case: {
17381738 \\ switch (i) {
1739 \\ @as(c_int, 0) => break :__case_0,
1740 \\ @as(c_int, 1)...@as(c_int, 3) => break :__case_1,
1741 \\ else => break :__default,
1742 \\ @as(c_int, 4) => break :__case_2,
1739 \\ @as(c_int, 0) => break :case,
1740 \\ @as(c_int, 1)...@as(c_int, 3) => break :case_1,
1741 \\ else => break :default,
1742 \\ @as(c_int, 4) => break :case_2,
17431743 \\ }
17441744 \\ }
17451745 \\ res = 1;
......@@ -1747,7 +1747,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
17471747 \\ res = 2;
17481748 \\ }
17491749 \\ res = (@as(c_int, 3) * i);
1750 \\ break :__switch;
1750 \\ break :@"switch";
17511751 \\ }
17521752 \\ res = 5;
17531753 \\ }
......@@ -2782,11 +2782,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
27822782 \\ var x = arg_x;
27832783 \\ return blk: {
27842784 \\ const tmp = x;
2785 \\ (blk: {
2785 \\ (blk_1: {
27862786 \\ const ref = &p;
2787 \\ const tmp_1 = ref.*;
2787 \\ const tmp_2 = ref.*;
27882788 \\ ref.* += 1;
2789 \\ break :blk tmp_1;
2789 \\ break :blk_1 tmp_2;
27902790 \\ }).?.* = tmp;
27912791 \\ break :blk tmp;
27922792 \\ };