aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-04-16 22:21:26 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-04-16 22:21:26 -0700
commit8cf0ef27790a96e784c368d00338229f205c95d9 (patch)
treed706896341cf35842e23a699adcb106eb8f13ffe
parent0409d433ba7f84885c782decbe06ec285c02c78c (diff)
downloadzig-8cf0ef27790a96e784c368d00338229f205c95d9.tar.gz
zig-8cf0ef27790a96e784c368d00338229f205c95d9.zip
AstGen: implement simple enums and decls for enums
-rw-r--r--src/AstGen.zig125
-rw-r--r--src/Zir.zig94
2 files changed, 162 insertions, 57 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index a66655c723..6b4dfc187b 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -2438,12 +2438,11 @@ fn structDeclInner(
const decl_inst = try gz.addBlock(tag, node);
try gz.instructions.append(gpa, decl_inst);
- if (field_index != 0) {
+ if (block_scope.instructions.items.len != 0) {
_ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
}
- try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
- @typeInfo(Zir.Inst.StructDecl).Struct.fields.len +
+ try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.StructDecl).Struct.fields.len +
bit_bag.items.len + @boolToInt(field_index != 0) + fields_data.items.len +
block_scope.instructions.items.len +
wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
@@ -2483,6 +2482,7 @@ fn containerDecl(
const tree = &astgen.file.tree;
const token_tags = tree.tokens.items(.tag);
const node_tags = tree.nodes.items(.tag);
+ const node_datas = tree.nodes.items(.data);
// We must not create any types until Sema. Here the goal is only to generate
// ZIR for all the field types, alignments, and default value expressions.
@@ -2594,22 +2594,12 @@ fn containerDecl(
},
);
}
- if (counts.values == 0 and counts.decls == 0 and arg_inst == .none) {
- return astgen.failNode(node, "TODO AstGen simple enums", .{});
- }
// In this case we must generate ZIR code for the tag values, similar to
// how structs are handled above.
const tag: Zir.Inst.Tag = if (counts.nonexhaustive_node == 0)
.enum_decl
else
.enum_decl_nonexhaustive;
- if (counts.total_fields == 0) {
- return gz.addPlNode(tag, node, Zir.Inst.EnumDecl{
- .tag_type = arg_inst,
- .fields_len = 0,
- .body_len = 0,
- });
- }
// The enum_decl instruction introduces a scope in which the decls of the enum
// are in scope, so that tag values can refer to decls within the enum itself.
@@ -2621,6 +2611,9 @@ fn containerDecl(
};
defer block_scope.instructions.deinit(gpa);
+ var wip_decls: WipDecls = .{};
+ defer wip_decls.deinit(gpa);
+
var fields_data = ArrayListUnmanaged(u32){};
defer fields_data.deinit(gpa);
@@ -2639,7 +2632,81 @@ fn containerDecl(
.container_field_init => tree.containerFieldInit(member_node),
.container_field_align => tree.containerFieldAlign(member_node),
.container_field => tree.containerField(member_node),
- else => continue,
+
+ .fn_decl => {
+ const fn_proto = node_datas[member_node].lhs;
+ const body = node_datas[member_node].rhs;
+ switch (node_tags[fn_proto]) {
+ .fn_proto_simple => {
+ var params: [1]ast.Node.Index = undefined;
+ try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoSimple(&params, fn_proto));
+ continue;
+ },
+ .fn_proto_multi => {
+ try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoMulti(fn_proto));
+ continue;
+ },
+ .fn_proto_one => {
+ var params: [1]ast.Node.Index = undefined;
+ try astgen.fnDecl(gz, &wip_decls, body, tree.fnProtoOne(&params, fn_proto));
+ continue;
+ },
+ .fn_proto => {
+ try astgen.fnDecl(gz, &wip_decls, body, tree.fnProto(fn_proto));
+ continue;
+ },
+ else => unreachable,
+ }
+ },
+ .fn_proto_simple => {
+ var params: [1]ast.Node.Index = undefined;
+ try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoSimple(&params, member_node));
+ continue;
+ },
+ .fn_proto_multi => {
+ try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoMulti(member_node));
+ continue;
+ },
+ .fn_proto_one => {
+ var params: [1]ast.Node.Index = undefined;
+ try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProtoOne(&params, member_node));
+ continue;
+ },
+ .fn_proto => {
+ try astgen.fnDecl(gz, &wip_decls, 0, tree.fnProto(member_node));
+ continue;
+ },
+
+ .global_var_decl => {
+ try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node));
+ continue;
+ },
+ .local_var_decl => {
+ try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node));
+ continue;
+ },
+ .simple_var_decl => {
+ try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node));
+ continue;
+ },
+ .aligned_var_decl => {
+ try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node));
+ continue;
+ },
+
+ .@"comptime" => {
+ try astgen.comptimeDecl(gz, scope, member_node);
+ continue;
+ },
+ .@"usingnamespace" => {
+ try astgen.usingnamespaceDecl(gz, scope, member_node);
+ continue;
+ },
+ .test_decl => {
+ try astgen.testDecl(gz, scope, member_node);
+ continue;
+ },
+ else => unreachable,
};
if (field_index % 32 == 0 and field_index != 0) {
try bit_bag.append(gpa, cur_bit_bag);
@@ -2663,27 +2730,45 @@ fn containerDecl(
field_index += 1;
}
- const empty_slot_count = 32 - (field_index % 32);
- cur_bit_bag >>= @intCast(u5, empty_slot_count);
+ {
+ const empty_slot_count = 32 - (field_index % 32);
+ cur_bit_bag >>= @intCast(u5, empty_slot_count);
+ }
+
+ if (wip_decls.decl_index != 0) {
+ const empty_slot_count = 16 - (wip_decls.decl_index % 16);
+ wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
+ }
const decl_inst = try gz.addBlock(tag, node);
try gz.instructions.append(gpa, decl_inst);
- _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
+ if (block_scope.instructions.items.len != 0) {
+ _ = try block_scope.addBreak(.break_inline, decl_inst, .void_value);
+ }
- try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
- @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len +
+ try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.EnumDecl).Struct.fields.len +
bit_bag.items.len + 1 + fields_data.items.len +
- block_scope.instructions.items.len);
+ block_scope.instructions.items.len +
+ wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
+ wip_decls.name_and_value.items.len);
const zir_datas = astgen.instructions.items(.data);
zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.EnumDecl{
.tag_type = arg_inst,
.body_len = @intCast(u32, block_scope.instructions.items.len),
.fields_len = @intCast(u32, field_index),
+ .decls_len = @intCast(u32, wip_decls.decl_index),
});
astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
astgen.extra.appendAssumeCapacity(cur_bit_bag);
astgen.extra.appendSliceAssumeCapacity(fields_data.items);
+
+ astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
+ if (wip_decls.decl_index != 0) {
+ astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
+ }
+ astgen.extra.appendSliceAssumeCapacity(wip_decls.name_and_value.items);
+
return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
},
.keyword_opaque => {
diff --git a/src/Zir.zig b/src/Zir.zig
index 423add0ab9..066be22be0 100644
--- a/src/Zir.zig
+++ b/src/Zir.zig
@@ -1591,11 +1591,20 @@ pub const Inst = struct {
/// field_name: u32,
/// value: Ref, // if corresponding bit is set
/// }
+ /// 3. decl_bits: u32 // for every 16 decls
+ /// - sets of 2 bits:
+ /// 0b0X: whether corresponding decl is pub
+ /// 0bX0: whether corresponding decl is exported
+ /// 4. decl: { // for every decls_len
+ /// name: u32, // null terminated string index
+ /// value: Index,
+ /// }
pub const EnumDecl = struct {
/// Can be `Ref.none`.
tag_type: Ref,
body_len: u32,
fields_len: u32,
+ decls_len: u32,
};
/// Trailing:
@@ -2231,6 +2240,7 @@ const Writer = struct {
const extra = self.code.extraData(Inst.EnumDecl, inst_data.payload_index);
const body = self.code.extra[extra.end..][0..extra.data.body_len];
const fields_len = extra.data.fields_len;
+ const decls_len = extra.data.decls_len;
const tag_ty_ref = extra.data.tag_type;
if (tag_ty_ref != .none) {
@@ -2238,53 +2248,63 @@ const Writer = struct {
try stream.writeAll(", ");
}
+ var extra_index: usize = undefined;
+
if (fields_len == 0) {
assert(body.len == 0);
- try stream.writeAll("{}, {}) ");
- try self.writeSrc(stream, inst_data.src());
- return;
- }
-
- try stream.writeAll("{\n");
- self.indent += 2;
- try self.writeBody(stream, body);
+ try stream.writeAll("{}, {}, {");
+ extra_index = extra.end;
+ } else {
+ try stream.writeAll("{\n");
+ self.indent += 2;
+ try self.writeBody(stream, body);
- try stream.writeByteNTimes(' ', self.indent - 2);
- try stream.writeAll("}, {\n");
+ try stream.writeByteNTimes(' ', self.indent - 2);
+ try stream.writeAll("}, {\n");
- const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
- const body_end = extra.end + body.len;
- var extra_index: usize = body_end + bit_bags_count;
- var bit_bag_index: usize = body_end;
- var cur_bit_bag: u32 = undefined;
- var field_i: u32 = 0;
- while (field_i < fields_len) : (field_i += 1) {
- if (field_i % 32 == 0) {
- cur_bit_bag = self.code.extra[bit_bag_index];
- bit_bag_index += 1;
- }
- const has_tag_value = @truncate(u1, cur_bit_bag) != 0;
- cur_bit_bag >>= 1;
+ const bit_bags_count = std.math.divCeil(usize, fields_len, 32) catch unreachable;
+ const body_end = extra.end + body.len;
+ extra_index = body_end + bit_bags_count;
+ var bit_bag_index: usize = body_end;
+ var cur_bit_bag: u32 = undefined;
+ var field_i: u32 = 0;
+ while (field_i < fields_len) : (field_i += 1) {
+ if (field_i % 32 == 0) {
+ cur_bit_bag = self.code.extra[bit_bag_index];
+ bit_bag_index += 1;
+ }
+ const has_tag_value = @truncate(u1, cur_bit_bag) != 0;
+ cur_bit_bag >>= 1;
- const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
- extra_index += 1;
+ const field_name = self.code.nullTerminatedString(self.code.extra[extra_index]);
+ extra_index += 1;
- try stream.writeByteNTimes(' ', self.indent);
- try stream.print("{}", .{std.zig.fmtId(field_name)});
+ try stream.writeByteNTimes(' ', self.indent);
+ try stream.print("{}", .{std.zig.fmtId(field_name)});
- if (has_tag_value) {
- const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
- extra_index += 1;
+ if (has_tag_value) {
+ const tag_value_ref = @intToEnum(Inst.Ref, self.code.extra[extra_index]);
+ extra_index += 1;
- try stream.writeAll(" = ");
- try self.writeInstRef(stream, tag_value_ref);
+ try stream.writeAll(" = ");
+ try self.writeInstRef(stream, tag_value_ref);
+ }
+ try stream.writeAll(",\n");
}
- try stream.writeAll(",\n");
+ self.indent -= 2;
+ try stream.writeByteNTimes(' ', self.indent);
+ try stream.writeAll("}, {");
+ }
+ if (decls_len == 0) {
+ try stream.writeAll("}) ");
+ } else {
+ try stream.writeAll("\n");
+ self.indent += 2;
+ try self.writeDecls(stream, decls_len, extra_index);
+ self.indent -= 2;
+ try stream.writeByteNTimes(' ', self.indent);
+ try stream.writeAll("}) ");
}
-
- self.indent -= 2;
- try stream.writeByteNTimes(' ', self.indent);
- try stream.writeAll("}) ");
try self.writeSrc(stream, inst_data.src());
}