AstGen: analyze inline switch cases

This commit is contained in:
Veikka Tuominen 2022-09-26 13:58:04 +03:00
parent 07a7c2f7c8
commit cccc4c3827
6 changed files with 63 additions and 31 deletions

View file

@ -6312,6 +6312,9 @@ fn switchExpr(
},
);
}
if (case.inline_token != null) {
return astgen.failTok(case_src, "cannot inline '_' prong", .{});
}
special_node = case_node;
special_prong = .under;
underscore_src = case_src;
@ -6365,8 +6368,8 @@ fn switchExpr(
var scalar_case_index: u32 = 0;
for (case_nodes) |case_node| {
const case = switch (node_tags[case_node]) {
.switch_case_one => tree.switchCaseOne(case_node),
.switch_case => tree.switchCase(case_node),
.switch_case_one, .switch_case_inline_one => tree.switchCaseOne(case_node),
.switch_case, .switch_case_inline => tree.switchCase(case_node),
else => unreachable,
};
@ -6506,7 +6509,8 @@ fn switchExpr(
const case_slice = case_scope.instructionsSlice();
const body_len = astgen.countBodyLenAfterFixups(case_slice);
try payloads.ensureUnusedCapacity(gpa, body_len);
payloads.items[body_len_index] = body_len;
const inline_bit = @as(u32, @boolToInt(case.inline_token != null)) << 31;
payloads.items[body_len_index] = body_len | inline_bit;
appendBodyWithFixupsArrayList(astgen, payloads, case_slice);
}
}
@ -6553,7 +6557,7 @@ fn switchExpr(
end_index += 3 + items_len + 2 * ranges_len;
}
const body_len = payloads.items[body_len_index];
const body_len = @truncate(u31, payloads.items[body_len_index]);
end_index += body_len;
switch (strat.tag) {
@ -9134,7 +9138,9 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
.@"usingnamespace",
.test_decl,
.switch_case,
.switch_case_inline,
.switch_case_one,
.switch_case_inline_one,
.container_field_init,
.container_field_align,
.container_field,

View file

@ -9237,7 +9237,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const special: struct { body: []const Zir.Inst.Index, end: usize } = switch (special_prong) {
.none => .{ .body = &.{}, .end = header_extra_index },
.under, .@"else" => blk: {
const body_len = sema.code.extra[header_extra_index];
const body_len = @truncate(u31, sema.code.extra[header_extra_index]);
const extra_body_start = header_extra_index + 1;
break :blk .{
.body = sema.code.extra[extra_body_start..][0..body_len],
@ -9307,7 +9307,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
extra_index += body_len;
@ -9328,7 +9328,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
extra_index += 1;
const ranges_len = sema.code.extra[extra_index];
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const items = sema.code.refSlice(extra_index, items_len);
extra_index += items_len + body_len;
@ -9407,7 +9407,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
extra_index += body_len;
@ -9427,7 +9427,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
extra_index += 1;
const ranges_len = sema.code.extra[extra_index];
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const items = sema.code.refSlice(extra_index, items_len);
extra_index += items_len + body_len;
@ -9549,7 +9549,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
extra_index += body_len;
@ -9570,7 +9570,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
extra_index += 1;
const ranges_len = sema.code.extra[extra_index];
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const items = sema.code.refSlice(extra_index, items_len);
extra_index += items_len;
@ -9647,7 +9647,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
extra_index += body_len;
@ -9668,7 +9668,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
extra_index += 1;
const ranges_len = sema.code.extra[extra_index];
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const items = sema.code.refSlice(extra_index, items_len);
extra_index += items_len + body_len;
@ -9732,7 +9732,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
extra_index += body_len;
@ -9752,7 +9752,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
extra_index += 1;
const ranges_len = sema.code.extra[extra_index];
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const items = sema.code.refSlice(extra_index, items_len);
extra_index += items_len + body_len;
@ -9832,7 +9832,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const body = sema.code.extra[extra_index..][0..body_len];
extra_index += body_len;
@ -9853,7 +9853,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
extra_index += 1;
const ranges_len = sema.code.extra[extra_index];
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const items = sema.code.refSlice(extra_index, items_len);
extra_index += items_len;
@ -9926,7 +9926,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const body = sema.code.extra[extra_index..][0..body_len];
extra_index += body_len;
@ -9988,7 +9988,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
extra_index += 1;
const ranges_len = sema.code.extra[extra_index];
extra_index += 1;
const body_len = sema.code.extra[extra_index];
const body_len = @truncate(u31, sema.code.extra[extra_index]);
extra_index += 1;
const items = sema.code.refSlice(extra_index, items_len);
extra_index += items_len;

View file

@ -2990,7 +2990,7 @@ pub const Inst = struct {
}
if (self.bits.specialProng() != .none) {
const body_len = zir.extra[extra_index];
const body_len = @truncate(u31, zir.extra[extra_index]);
extra_index += 1;
const body = zir.extra[extra_index..][0..body_len];
extra_index += body.len;
@ -3000,7 +3000,7 @@ pub const Inst = struct {
while (true) : (scalar_i += 1) {
const item = @intToEnum(Ref, zir.extra[extra_index]);
extra_index += 1;
const body_len = zir.extra[extra_index];
const body_len = @truncate(u31, zir.extra[extra_index]);
extra_index += 1;
const body = zir.extra[extra_index..][0..body_len];
extra_index += body.len;
@ -3029,7 +3029,7 @@ pub const Inst = struct {
var extra_index: usize = extra_end + 1;
if (self.bits.specialProng() != .none) {
const body_len = zir.extra[extra_index];
const body_len = @truncate(u31, zir.extra[extra_index]);
extra_index += 1;
const body = zir.extra[extra_index..][0..body_len];
extra_index += body.len;
@ -3038,7 +3038,7 @@ pub const Inst = struct {
var scalar_i: usize = 0;
while (scalar_i < self.bits.scalar_cases_len) : (scalar_i += 1) {
extra_index += 1;
const body_len = zir.extra[extra_index];
const body_len = @truncate(u31, zir.extra[extra_index]);
extra_index += 1;
extra_index += body_len;
}
@ -3046,7 +3046,7 @@ pub const Inst = struct {
while (true) : (multi_i += 1) {
const items_len = zir.extra[extra_index];
extra_index += 2;
const body_len = zir.extra[extra_index];
const body_len = @truncate(u31, zir.extra[extra_index]);
extra_index += 1;
const items = zir.refSlice(extra_index, items_len);
extra_index += items_len;
@ -3858,7 +3858,7 @@ fn findDeclsSwitch(
const special_prong = extra.data.bits.specialProng();
if (special_prong != .none) {
const body_len = zir.extra[extra_index];
const body_len = @truncate(u31, zir.extra[extra_index]);
extra_index += 1;
const body = zir.extra[extra_index..][0..body_len];
extra_index += body.len;
@ -3871,7 +3871,7 @@ fn findDeclsSwitch(
var scalar_i: usize = 0;
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
extra_index += 1;
const body_len = zir.extra[extra_index];
const body_len = @truncate(u31, zir.extra[extra_index]);
extra_index += 1;
const body = zir.extra[extra_index..][0..body_len];
extra_index += body_len;
@ -3886,7 +3886,7 @@ fn findDeclsSwitch(
extra_index += 1;
const ranges_len = zir.extra[extra_index];
extra_index += 1;
const body_len = zir.extra[extra_index];
const body_len = @truncate(u31, zir.extra[extra_index]);
extra_index += 1;
const items = zir.refSlice(extra_index, items_len);
extra_index += items_len;

View file

@ -1868,14 +1868,15 @@ const Writer = struct {
else => break :else_prong,
};
const body_len = self.code.extra[extra_index];
const body_len = @truncate(u31, self.code.extra[extra_index]);
const inline_text = if (self.code.extra[extra_index] >> 31 != 0) "inline " else "";
extra_index += 1;
const body = self.code.extra[extra_index..][0..body_len];
extra_index += body.len;
try stream.writeAll(",\n");
try stream.writeByteNTimes(' ', self.indent);
try stream.print("{s} => ", .{prong_name});
try stream.print("{s}{s} => ", .{ inline_text, prong_name });
try self.writeBracedBody(stream, body);
}
@ -1885,13 +1886,15 @@ const Writer = struct {
while (scalar_i < scalar_cases_len) : (scalar_i += 1) {
const item_ref = @intToEnum(Zir.Inst.Ref, self.code.extra[extra_index]);
extra_index += 1;
const body_len = self.code.extra[extra_index];
const body_len = @truncate(u31, self.code.extra[extra_index]);
const is_inline = self.code.extra[extra_index] >> 31 != 0;
extra_index += 1;
const body = self.code.extra[extra_index..][0..body_len];
extra_index += body_len;
try stream.writeAll(",\n");
try stream.writeByteNTimes(' ', self.indent);
if (is_inline) try stream.writeAll("inline ");
try self.writeInstRef(stream, item_ref);
try stream.writeAll(" => ");
try self.writeBracedBody(stream, body);
@ -1904,13 +1907,15 @@ const Writer = struct {
extra_index += 1;
const ranges_len = self.code.extra[extra_index];
extra_index += 1;
const body_len = self.code.extra[extra_index];
const body_len = @truncate(u31, self.code.extra[extra_index]);
const is_inline = self.code.extra[extra_index] >> 31 != 0;
extra_index += 1;
const items = self.code.refSlice(extra_index, items_len);
extra_index += items_len;
try stream.writeAll(",\n");
try stream.writeByteNTimes(' ', self.indent);
if (is_inline) try stream.writeAll("inline ");
for (items) |item_ref, item_i| {
if (item_i != 0) try stream.writeAll(", ");

View file

@ -6987,6 +6987,12 @@ static bool astgen_switch_prong_expr(Stage1AstGen *ag, Scope *scope, AstNode *sw
assert(switch_node->type == NodeTypeSwitchExpr);
assert(prong_node->type == NodeTypeSwitchProng);
if (prong_node->data.switch_prong.is_inline) {
exec_add_error_node(ag->codegen, ag->exec, prong_node,
buf_sprintf("inline switch cases not supported by stage1"));
return ag->codegen->invalid_inst_src;
}
AstNode *expr_node = prong_node->data.switch_prong.expr;
AstNode *var_symbol_node = prong_node->data.switch_prong.var_symbol;
Scope *child_scope;

View file

@ -0,0 +1,15 @@
const E = enum(u8) { a, b, c, d, _ };
pub export fn entry() void {
var x: E = .a;
switch (x) {
inline .a, .b => |aorb| @compileLog(aorb),
.c, .d => |cord| @compileLog(cord),
inline _ => {},
}
}
// error
// backend=stage2
// target=native
//
// :7:16: error: cannot inline '_' prong