Skip to content
This repository was archived by the owner on Nov 26, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 11 additions & 21 deletions src/Translator.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1618,7 +1618,10 @@ fn transCompoundStmtInline(t: *Translator, compound: Node.CompoundStmt, block: *
const result = try t.transStmt(&block.base, stmt);
switch (result.tag()) {
.declaration, .empty_block => {},
else => try block.statements.append(t.gpa, result),
else => {
try block.statements.append(t.gpa, result);
if (result.isNoreturn()) return;
},
}
}
}
Expand Down Expand Up @@ -1754,7 +1757,7 @@ fn transDoWhileStmt(t: *Translator, scope: *Scope, do_stmt: Node.DoWhileStmt) Tr
};

var body_node = try t.transStmt(&loop_scope, do_stmt.body);
if (body_node.isNoreturn(true)) {
if (body_node.isNoreturn()) {
// The body node ends in a noreturn statement. Simply put it in a while (true)
// in case it contains breaks or continues.
} else if (do_stmt.body.get(t.tree) == .compound_stmt) {
Expand Down Expand Up @@ -1974,8 +1977,6 @@ fn transSwitchProngStmt(
body: []const Node.Index,
) TransError!ZigNode {
switch (stmt.get(t.tree)) {
.break_stmt => return ZigTag.@"break".init(),
.return_stmt => return t.transStmt(scope, stmt),
.case_stmt, .default_stmt => unreachable,
else => {
var block_scope = try Scope.Block.init(t, scope, false);
Expand All @@ -1996,15 +1997,6 @@ fn transSwitchProngStmtInline(
) TransError!void {
for (body) |stmt| {
switch (stmt.get(t.tree)) {
.return_stmt => {
const result = try t.transStmt(&block.base, stmt);
try block.statements.append(t.gpa, result);
return;
},
.break_stmt => {
try block.statements.append(t.gpa, ZigTag.@"break".init());
return;
},
.case_stmt => |case_stmt| {
var sub = case_stmt.body;
while (true) switch (sub.get(t.tree)) {
Expand All @@ -2015,7 +2007,7 @@ fn transSwitchProngStmtInline(
const result = try t.transStmt(&block.base, sub);
assert(result.tag() != .declaration);
try block.statements.append(t.gpa, result);
if (result.isNoreturn(true)) return;
if (result.isNoreturn()) return;
},
.default_stmt => |default_stmt| {
var sub = default_stmt.body;
Expand All @@ -2027,18 +2019,16 @@ fn transSwitchProngStmtInline(
const result = try t.transStmt(&block.base, sub);
assert(result.tag() != .declaration);
try block.statements.append(t.gpa, result);
if (result.isNoreturn(true)) return;
},
.compound_stmt => |compound_stmt| {
const result = try t.transCompoundStmt(&block.base, compound_stmt);
try block.statements.append(t.gpa, result);
if (result.isNoreturn(true)) return;
if (result.isNoreturn()) return;
},
else => {
const result = try t.transStmt(&block.base, stmt);
switch (result.tag()) {
.declaration, .empty_block => {},
else => try block.statements.append(t.gpa, result),
else => {
try block.statements.append(t.gpa, result);
if (result.isNoreturn()) return;
},
}
},
}
Expand Down
19 changes: 10 additions & 9 deletions src/ast.zig
Original file line number Diff line number Diff line change
Expand Up @@ -455,14 +455,14 @@ pub const Node = extern union {
return .{ .ptr_otherwise = payload };
}

pub fn isNoreturn(node: Node, break_counts: bool) bool {
switch (node.tag()) {
pub fn isNoreturn(node: Node) bool {
return switch (node.tag()) {
.block => {
const block_node = node.castTag(.block).?;
if (block_node.data.stmts.len == 0) return false;

const last = block_node.data.stmts[block_node.data.stmts.len - 1];
return last.isNoreturn(break_counts);
return last.isNoreturn();
},
.@"switch" => {
const switch_node = node.castTag(.@"switch").?;
Expand All @@ -475,15 +475,16 @@ pub const Node = extern union {
else
unreachable;

if (!body.isNoreturn(break_counts)) return false;
if (!body.isNoreturn()) return false;
}
return true;
},
.@"return", .return_void => return true,
.@"break" => if (break_counts) return true,
else => {},
}
return false;
.@"return", .return_void => true,
.@"break" => true,
.@"continue" => true,
.@"unreachable" => true,
else => false,
};
}

pub fn isBoolRes(res: Node) bool {
Expand Down
12 changes: 6 additions & 6 deletions test/cases/translate/bool_not.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ int foo() {
int a;
float b;
void *c;
return !(a == 0);
return !a;
return !b;
if (1) return !(a == 0);
if (1) return !a;
if (1) return !b;
return !c;
}

Expand All @@ -17,8 +17,8 @@ int foo() {
// _ = &b;
// var c: ?*anyopaque = undefined;
// _ = &c;
// return @intFromBool(!(a == @as(c_int, 0)));
// return @intFromBool(!(a != 0));
// return @intFromBool(!(b != 0));
// if (true) return @intFromBool(!(a == @as(c_int, 0)));
// if (true) return @intFromBool(!(a != 0));
// if (true) return @intFromBool(!(b != 0));
// return @intFromBool(!(c != null));
// }
67 changes: 67 additions & 0 deletions test/cases/translate/continue_in_switch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
int entry(int i) {
int res = i;
while (1) switch (res) {
case 0:
res += 1;
case 1:
continue;
case 2: {
continue;
}
case 3:
if (res == 42) return - 1;
res = 42;
continue;
case 4:
return 1;
case 5:
res = 10;
default:
break;
};
return res;
}

// translate
//
// pub export fn entry(arg_i: c_int) c_int {
// var i = arg_i;
// _ = &i;
// var res: c_int = i;
// _ = &res;
// while (true) {
// while (true) {
// switch (res) {
// @as(c_int, 0) => {
// res += 1;
// continue;
// },
// @as(c_int, 1) => {
// continue;
// },
// @as(c_int, 2) => {
// {
// continue;
// }
// },
// @as(c_int, 3) => {
// if (res == @as(c_int, 42)) return -@as(c_int, 1);
// res = 42;
// continue;
// },
// @as(c_int, 4) => {
// return 1;
// },
// @as(c_int, 5) => {
// res = 10;
// break;
// },
// else => {
// break;
// },
// }
// break;
// }
// }
// return res;
// }
12 changes: 12 additions & 0 deletions test/cases/translate/do_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ void foo(void) {
do
b = b -1;
while (b);
do {
__builtin_unreachable();
} while (0);
do {
continue;
} while (1);
}

// translate
Expand All @@ -25,4 +31,10 @@ void foo(void) {
// b = b - @as(c_int, 1);
// if (!(b != 0)) break;
// }
// while (true) {
// unreachable;
// }
// while (true) {
// continue;
// }
// }
10 changes: 10 additions & 0 deletions test/cases/translate/early_return.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
static unsigned long early_return(void) {
return 8 * 1024 * 1024;
return 2 * 1024 * 1024;
}

// translate
//
// pub fn early_return() callconv(.c) c_ulong {
// return @bitCast(@as(c_long, (@as(c_int, 8) * @as(c_int, 1024)) * @as(c_int, 1024)));
// }
4 changes: 3 additions & 1 deletion test/cases/translate/switch_on_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ void switch_fn(int i) {
// @as(c_int, 6) => {
// while (true) {
// switch (res) {
// @as(c_int, 9) => break,
// @as(c_int, 9) => {
// break;
// },
// else => {},
// }
// break;
Expand Down