Commit c5368ba20c
Changed files (2)
src-self-hosted
test
src-self-hosted/translate_c.zig
@@ -61,7 +61,8 @@ const Scope = struct {
pending_block: Block,
cases: []*ast.Node,
case_index: usize,
- has_default: bool = false,
+ switch_label: ?[]const u8,
+ default_label: ?[]const u8,
};
/// Used for the scope of condition expressions, for example `if (cond)`.
@@ -73,7 +74,7 @@ const Scope = struct {
fn getBlockScope(self: *Condition, c: *Context) !*Block {
if (self.block) |*b| return b;
- self.block = try Block.init(c, &self.base, "blk");
+ self.block = try Block.init(c, &self.base, true);
return &self.block.?;
}
@@ -93,21 +94,22 @@ const Scope = struct {
mangle_count: u32 = 0,
lbrace: ast.TokenIndex,
- fn init(c: *Context, parent: *Scope, label: ?[]const u8) !Block {
- return Block{
+ fn init(c: *Context, parent: *Scope, labeled: bool) !Block {
+ var blk = Block{
.base = .{
.id = .Block,
.parent = parent,
},
.statements = std.ArrayList(*ast.Node).init(c.gpa),
.variables = AliasList.init(c.gpa),
- .label = if (label) |l| blk: {
- const ll = try appendIdentifier(c, l);
- _ = try appendToken(c, .Colon, ":");
- break :blk ll;
- } else null,
+ .label = null,
.lbrace = try appendToken(c, .LBrace, "{"),
};
+ if (labeled) {
+ blk.label = try appendIdentifier(c, try blk.makeMangledName(c, "blk"));
+ _ = try appendToken(c, .Colon, ":");
+ }
+ return blk;
}
fn deinit(self: *Block) void {
@@ -577,7 +579,7 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
// actual function definition with body
const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
- var block_scope = try Scope.Block.init(rp.c, &c.global_scope.base, null);
+ var block_scope = try Scope.Block.init(rp.c, &c.global_scope.base, false);
defer block_scope.deinit();
var scope = &block_scope.base;
@@ -1307,7 +1309,7 @@ fn transBinaryOperator(
const rhs = try transExpr(rp, &block_scope.base, ZigClangBinaryOperator_getRHS(stmt), .used, .r_value);
if (expr) {
_ = try appendToken(rp.c, .Semicolon, ";");
- const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, rhs);
+ const break_node = try transCreateNodeBreak(rp.c, block_scope.label, rhs);
try block_scope.statements.append(&break_node.base);
const block_node = try block_scope.complete(rp.c);
const rparen = try appendToken(rp.c, .RParen, ")");
@@ -1476,7 +1478,7 @@ fn transCompoundStmtInline(
}
fn transCompoundStmt(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangCompoundStmt) TransError!*ast.Node {
- var block_scope = try Scope.Block.init(rp.c, scope, null);
+ var block_scope = try Scope.Block.init(rp.c, scope, false);
defer block_scope.deinit();
try transCompoundStmtInline(rp, &block_scope.base, stmt, &block_scope);
const node = try block_scope.complete(rp.c);
@@ -2587,7 +2589,7 @@ fn transForLoop(
defer if (block_scope) |*bs| bs.deinit();
if (ZigClangForStmt_getInit(stmt)) |init| {
- block_scope = try Scope.Block.init(rp.c, scope, null);
+ block_scope = try Scope.Block.init(rp.c, scope, false);
loop_scope.parent = &block_scope.?.base;
const init_node = try transStmt(rp, &block_scope.?.base, init, .unused, .r_value);
try block_scope.?.statements.append(init_node);
@@ -2673,17 +2675,19 @@ fn transSwitch(
.cases = switch_node.cases(),
.case_index = 0,
.pending_block = undefined,
+ .default_label = null,
+ .switch_label = null,
};
// tmp block that all statements will go before being picked up by a case or default
- var block_scope = try Scope.Block.init(rp.c, &switch_scope.base, null);
+ var block_scope = try Scope.Block.init(rp.c, &switch_scope.base, false);
defer block_scope.deinit();
// Note that we do not defer a deinit here; the switch_scope.pending_block field
// has its own memory management. This resource is freed inside `transCase` and
// then the final pending_block is freed at the bottom of this function with
// pending_block.deinit().
- switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null);
+ switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
try switch_scope.pending_block.statements.append(&switch_node.base);
const last = try transStmt(rp, &block_scope.base, ZigClangSwitchStmt_getBody(stmt), .unused, .r_value);
@@ -2698,11 +2702,19 @@ fn transSwitch(
switch_scope.pending_block.statements.appendAssumeCapacity(n);
}
- switch_scope.pending_block.label = try appendIdentifier(rp.c, "__switch");
- _ = try appendToken(rp.c, .Colon, ":");
- if (!switch_scope.has_default) {
+ if (switch_scope.default_label == null) {
+ switch_scope.switch_label = try block_scope.makeMangledName(rp.c, "switch");
+ }
+ if (switch_scope.switch_label) |l| {
+ switch_scope.pending_block.label = try appendIdentifier(rp.c, l);
+ _ = try appendToken(rp.c, .Colon, ":");
+ }
+ if (switch_scope.default_label == null) {
const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));
- else_prong.expr = &(try transCreateNodeBreak(rp.c, "__switch", null)).base;
+ else_prong.expr = blk: {
+ var br = try CtrlFlow.init(rp.c, .Break, switch_scope.switch_label.?);
+ break :blk &(try br.finish(null)).base;
+ };
_ = try appendToken(rp.c, .Comma, ",");
if (switch_scope.case_index >= switch_scope.cases.len)
@@ -2726,7 +2738,7 @@ fn transCase(
) TransError!*ast.Node {
const block_scope = scope.findBlockScope(rp.c) catch unreachable;
const switch_scope = scope.getSwitch();
- const label = try std.fmt.allocPrint(rp.c.arena, "__case_{}", .{switch_scope.case_index - @boolToInt(switch_scope.has_default)});
+ const label = try block_scope.makeMangledName(rp.c, "case");
_ = try appendToken(rp.c, .Semicolon, ";");
const expr = if (ZigClangCaseStmt_getRHS(stmt)) |rhs| blk: {
@@ -2746,7 +2758,10 @@ fn transCase(
try transExpr(rp, scope, ZigClangCaseStmt_getLHS(stmt), .used, .r_value);
const switch_prong = try transCreateNodeSwitchCase(rp.c, expr);
- switch_prong.expr = &(try transCreateNodeBreak(rp.c, label, null)).base;
+ switch_prong.expr = blk: {
+ var br = try CtrlFlow.init(rp.c, .Break, label);
+ break :blk &(try br.finish(null)).base;
+ };
_ = try appendToken(rp.c, .Comma, ",");
if (switch_scope.case_index >= switch_scope.cases.len)
@@ -2763,7 +2778,7 @@ fn transCase(
const pending_node = try switch_scope.pending_block.complete(rp.c);
switch_scope.pending_block.deinit();
- switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null);
+ switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
try switch_scope.pending_block.statements.append(&pending_node.base);
@@ -2777,12 +2792,14 @@ fn transDefault(
) TransError!*ast.Node {
const block_scope = scope.findBlockScope(rp.c) catch unreachable;
const switch_scope = scope.getSwitch();
- const label = "__default";
- switch_scope.has_default = true;
+ switch_scope.default_label = try block_scope.makeMangledName(rp.c, "default");
_ = try appendToken(rp.c, .Semicolon, ";");
const else_prong = try transCreateNodeSwitchCase(rp.c, try transCreateNodeSwitchElse(rp.c));
- else_prong.expr = &(try transCreateNodeBreak(rp.c, label, null)).base;
+ else_prong.expr = blk: {
+ var br = try CtrlFlow.init(rp.c, .Break, switch_scope.default_label.?);
+ break :blk &(try br.finish(null)).base;
+ };
_ = try appendToken(rp.c, .Comma, ",");
if (switch_scope.case_index >= switch_scope.cases.len)
@@ -2790,7 +2807,7 @@ fn transDefault(
switch_scope.cases[switch_scope.case_index] = &else_prong.base;
switch_scope.case_index += 1;
- switch_scope.pending_block.label = try appendIdentifier(rp.c, label);
+ switch_scope.pending_block.label = try appendIdentifier(rp.c, switch_scope.default_label.?);
_ = try appendToken(rp.c, .Colon, ":");
// take all pending statements
@@ -2799,7 +2816,7 @@ fn transDefault(
const pending_node = try switch_scope.pending_block.complete(rp.c);
switch_scope.pending_block.deinit();
- switch_scope.pending_block = try Scope.Block.init(rp.c, scope, null);
+ switch_scope.pending_block = try Scope.Block.init(rp.c, scope, false);
try switch_scope.pending_block.statements.append(&pending_node.base);
return transStmt(rp, scope, ZigClangDefaultStmt_getSubStmt(stmt), .unused, .r_value);
@@ -2894,7 +2911,7 @@ fn transStmtExpr(rp: RestorePoint, scope: *Scope, stmt: *const ZigClangStmtExpr,
return transCompoundStmt(rp, scope, comp);
}
const lparen = try appendToken(rp.c, .LParen, "(");
- var block_scope = try Scope.Block.init(rp.c, scope, "blk");
+ var block_scope = try Scope.Block.init(rp.c, scope, true);
defer block_scope.deinit();
var it = ZigClangCompoundStmt_body_begin(comp);
@@ -3209,7 +3226,7 @@ fn transCreatePreCrement(
// zig: _ref.* += 1;
// zig: break :blk _ref.*
// zig: })
- var block_scope = try Scope.Block.init(rp.c, scope, "blk");
+ var block_scope = try Scope.Block.init(rp.c, scope, true);
defer block_scope.deinit();
const ref = try block_scope.makeMangledName(rp.c, "ref");
@@ -3239,7 +3256,7 @@ fn transCreatePreCrement(
const assign = try transCreateNodeInfixOp(rp, scope, ref_node, op, token, one, .used, false);
try block_scope.statements.append(assign);
- const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, ref_node);
+ const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node);
try block_scope.statements.append(&break_node.base);
const block_node = try block_scope.complete(rp.c);
// semicolon must immediately follow rbrace because it is the last token in a block
@@ -3283,7 +3300,7 @@ fn transCreatePostCrement(
// zig: _ref.* += 1;
// zig: break :blk _tmp
// zig: })
- var block_scope = try Scope.Block.init(rp.c, scope, "blk");
+ var block_scope = try Scope.Block.init(rp.c, scope, true);
defer block_scope.deinit();
const ref = try block_scope.makeMangledName(rp.c, "ref");
@@ -3458,7 +3475,7 @@ fn transCreateCompoundAssign(
// zig: _ref.* = _ref.* + rhs;
// zig: break :blk _ref.*
// zig: })
- var block_scope = try Scope.Block.init(rp.c, scope, "blk");
+ var block_scope = try Scope.Block.init(rp.c, scope, true);
defer block_scope.deinit();
const ref = try block_scope.makeMangledName(rp.c, "ref");
@@ -3526,7 +3543,7 @@ fn transCreateCompoundAssign(
try block_scope.statements.append(assign);
}
- const break_node = try transCreateNodeBreakToken(rp.c, block_scope.label, ref_node);
+ const break_node = try transCreateNodeBreak(rp.c, block_scope.label, ref_node);
try block_scope.statements.append(&break_node.base);
const block_node = try block_scope.complete(rp.c);
const grouped_expr = try rp.c.arena.create(ast.Node.GroupedExpression);
@@ -3602,8 +3619,16 @@ fn transCPtrCast(
fn transBreak(rp: RestorePoint, scope: *Scope) TransError!*ast.Node {
const break_scope = scope.getBreakableScope();
- const label_text: ?[]const u8 = if (break_scope.id == .Switch) "__switch" else null;
- const br = try transCreateNodeBreak(rp.c, label_text, null);
+ const label_text: ?[]const u8 = if (break_scope.id == .Switch) blk: {
+ const swtch = @fieldParentPtr(Scope.Switch, "base", break_scope);
+ const block_scope = try scope.findBlockScope(rp.c);
+ swtch.switch_label = try block_scope.makeMangledName(rp.c, "switch");
+ break :blk swtch.switch_label;
+ } else
+ null;
+
+ var cf = try CtrlFlow.init(rp.c, .Break, label_text);
+ const br = try cf.finish(null);
_ = try appendToken(rp.c, .Semicolon, ";");
return &br.base;
}
@@ -3634,7 +3659,7 @@ fn transBinaryConditionalOperator(rp: RestorePoint, scope: *Scope, stmt: *const
// })
const lparen = try appendToken(rp.c, .LParen, "(");
- var block_scope = try Scope.Block.init(rp.c, scope, "blk");
+ var block_scope = try Scope.Block.init(rp.c, scope, true);
defer block_scope.deinit();
const mangled_name = try block_scope.makeMangledName(rp.c, "cond_temp");
@@ -4082,8 +4107,7 @@ fn transCreateNodeAssign(
// zig: lhs = _tmp;
// zig: break :blk _tmp
// zig: })
- const label_name = "blk";
- var block_scope = try Scope.Block.init(rp.c, scope, label_name);
+ var block_scope = try Scope.Block.init(rp.c, scope, true);
defer block_scope.deinit();
const tmp = try block_scope.makeMangledName(rp.c, "tmp");
@@ -4118,7 +4142,7 @@ fn transCreateNodeAssign(
try block_scope.statements.append(assign);
const break_node = blk: {
- var tmp_ctrl_flow = try CtrlFlow.init(rp.c, .Break, label_name);
+ var tmp_ctrl_flow = try CtrlFlow.init(rp.c, .Break, tokenSlice(rp.c, block_scope.label.?));
const rhs_expr = try transCreateNodeIdentifier(rp.c, tmp);
break :blk try tmp_ctrl_flow.finish(rhs_expr);
};
@@ -4495,23 +4519,12 @@ fn transCreateNodeElse(c: *Context) !*ast.Node.Else {
return node;
}
-fn transCreateNodeBreakToken(
- c: *Context,
- label: ?ast.TokenIndex,
- rhs: ?*ast.Node,
-) !*ast.Node.ControlFlowExpression {
- const other_token = label orelse return transCreateNodeBreak(c, null, rhs);
- const loc = c.token_locs.items[other_token];
- const label_name = c.source_buffer.items[loc.start..loc.end];
- return transCreateNodeBreak(c, label_name, rhs);
-}
-
fn transCreateNodeBreak(
c: *Context,
- label: ?[]const u8,
+ label: ?ast.TokenIndex,
rhs: ?*ast.Node,
) !*ast.Node.ControlFlowExpression {
- var ctrl_flow = try CtrlFlow.init(c, .Break, label);
+ var ctrl_flow = try CtrlFlow.init(c, .Break, if (label) |l| tokenSlice(c, l) else null);
return ctrl_flow.finish(rhs);
}
@@ -5362,7 +5375,7 @@ fn transMacroDefine(c: *Context, m: *MacroCtx) ParseError!void {
}
fn transMacroFnDefine(c: *Context, m: *MacroCtx) ParseError!void {
- var block_scope = try Scope.Block.init(c, &c.global_scope.base, null);
+ var block_scope = try Scope.Block.init(c, &c.global_scope.base, false);
defer block_scope.deinit();
const scope = &block_scope.base;
@@ -5475,8 +5488,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
},
.Comma => {
_ = try appendToken(c, .Semicolon, ";");
- const label_name = "blk";
- var block_scope = try Scope.Block.init(c, scope, label_name);
+ var block_scope = try Scope.Block.init(c, scope, true);
defer block_scope.deinit();
var last = node;
@@ -5501,7 +5513,7 @@ fn parseCExpr(c: *Context, m: *MacroCtx, scope: *Scope) ParseError!*ast.Node {
}
}
- const break_node = try transCreateNodeBreak(c, label_name, last);
+ const break_node = try transCreateNodeBreak(c, block_scope.label, last);
try block_scope.statements.append(&break_node.base);
const block_node = try block_scope.complete(c);
return &block_node.base;
test/translate_c.zig
@@ -1730,16 +1730,16 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub export fn switch_fn(arg_i: c_int) c_int {
\\ var i = arg_i;
\\ var res: c_int = 0;
- \\ __switch: {
- \\ __case_2: {
- \\ __default: {
- \\ __case_1: {
- \\ __case_0: {
+ \\ @"switch": {
+ \\ case_2: {
+ \\ default: {
+ \\ case_1: {
+ \\ case: {
\\ switch (i) {
- \\ @as(c_int, 0) => break :__case_0,
- \\ @as(c_int, 1)...@as(c_int, 3) => break :__case_1,
- \\ else => break :__default,
- \\ @as(c_int, 4) => break :__case_2,
+ \\ @as(c_int, 0) => break :case,
+ \\ @as(c_int, 1)...@as(c_int, 3) => break :case_1,
+ \\ else => break :default,
+ \\ @as(c_int, 4) => break :case_2,
\\ }
\\ }
\\ res = 1;
@@ -1747,7 +1747,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ res = 2;
\\ }
\\ res = (@as(c_int, 3) * i);
- \\ break :__switch;
+ \\ break :@"switch";
\\ }
\\ res = 5;
\\ }
@@ -2782,11 +2782,11 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ var x = arg_x;
\\ return blk: {
\\ const tmp = x;
- \\ (blk: {
+ \\ (blk_1: {
\\ const ref = &p;
- \\ const tmp_1 = ref.*;
+ \\ const tmp_2 = ref.*;
\\ ref.* += 1;
- \\ break :blk tmp_1;
+ \\ break :blk_1 tmp_2;
\\ }).?.* = tmp;
\\ break :blk tmp;
\\ };