Commit 646eb1fa93
Changed files (2)
src/AstGen.zig
@@ -3254,6 +3254,12 @@ fn structDeclInner(
.fields_len = @intCast(u32, field_index),
.decls_len = @intCast(u32, wip_decls.decl_index),
});
+ 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.payload.items);
+
astgen.extra.appendSliceAssumeCapacity(block_scope.instructions.items);
astgen.extra.appendSliceAssumeCapacity(bit_bag.items); // Likely empty.
@@ -3262,12 +3268,6 @@ fn structDeclInner(
}
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.payload.items);
-
return gz.indexToRef(decl_inst);
}
@@ -3479,18 +3479,18 @@ fn unionDeclInner(
.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.payload.items);
+ 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);
+
return gz.indexToRef(decl_inst);
}
@@ -3811,11 +3811,121 @@ fn containerDecl(
.fields_len = @intCast(u32, field_index),
.decls_len = @intCast(u32, wip_decls.decl_index),
});
+ 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.payload.items);
+
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);
+ return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
+ },
+ .keyword_opaque => {
+ var wip_decls: WipDecls = .{};
+ defer wip_decls.deinit(gpa);
+
+ for (container_decl.ast.members) |member_node| {
+ const member = switch (node_tags[member_node]) {
+ .container_field_init => tree.containerFieldInit(member_node),
+ .container_field_align => tree.containerFieldAlign(member_node),
+ .container_field => tree.containerField(member_node),
+
+ .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(¶ms, 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(¶ms, 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(¶ms, 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(¶ms, 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,
+ };
+ }
+ {
+ const empty_slot_count = WipDecls.fields_per_u32 - (wip_decls.decl_index % WipDecls.fields_per_u32);
+ if (empty_slot_count < WipDecls.fields_per_u32) {
+ wip_decls.cur_bit_bag >>= @intCast(u5, empty_slot_count * WipDecls.bits_per_field);
+ }
+ }
+ const decl_inst = try gz.addBlock(.opaque_decl, node);
+ try gz.instructions.append(gpa, decl_inst);
+
+ try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.OpaqueDecl).Struct.fields.len +
+ wip_decls.bit_bag.items.len + @boolToInt(wip_decls.decl_index != 0) +
+ wip_decls.payload.items.len);
+ const zir_datas = astgen.instructions.items(.data);
+ zir_datas[decl_inst].pl_node.payload_index = astgen.addExtraAssumeCapacity(Zir.Inst.OpaqueDecl{
+ .decls_len = @intCast(u32, wip_decls.decl_index),
+ });
astgen.extra.appendSliceAssumeCapacity(wip_decls.bit_bag.items); // Likely empty.
if (wip_decls.decl_index != 0) {
astgen.extra.appendAssumeCapacity(wip_decls.cur_bit_bag);
@@ -3824,10 +3934,6 @@ fn containerDecl(
return rvalue(gz, scope, rl, gz.indexToRef(decl_inst), node);
},
- .keyword_opaque => {
- const result = try gz.addNode(.opaque_decl, node);
- return rvalue(gz, scope, rl, result, node);
- },
else => unreachable,
}
}
src/Zir.zig
@@ -312,7 +312,7 @@ pub const Inst = struct {
/// Same as `enum_decl`, except the enum is non-exhaustive.
enum_decl_nonexhaustive,
/// An opaque type definition. Provides an AST node only.
- /// Uses the `node` union field.
+ /// Uses the `pl_node` union field. Payload is `OpaqueDecl`.
opaque_decl,
/// An error set type definition. Contains a list of field names.
/// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
@@ -2368,29 +2368,29 @@ pub const Inst = struct {
};
/// Trailing:
- /// 0. inst: Index // for every body_len
- /// 1. has_bits: u32 // for every 16 fields
- /// - sets of 2 bits:
- /// 0b0X: whether corresponding field has an align expression
- /// 0bX0: whether corresponding field has a default expression
- /// 2. fields: { // for every fields_len
- /// field_name: u32,
- /// field_type: Ref,
- /// align: Ref, // if corresponding bit is set
- /// default_value: Ref, // if corresponding bit is set
- /// }
- /// 3. decl_bits: u32 // for every 8 decls
+ /// 0. decl_bits: u32 // for every 8 decls
/// - sets of 4 bits:
/// 0b000X: whether corresponding decl is pub
/// 0b00X0: whether corresponding decl is exported
/// 0b0X00: whether corresponding decl has an align expression
/// 0bX000: whether corresponding decl has a linksection expression
- /// 4. decl: { // for every decls_len
+ /// 1. decl: { // for every decls_len
/// name: u32, // null terminated string index
/// value: Index,
/// align: Ref, // if corresponding bit is set
/// link_section: Ref, // if corresponding bit is set
/// }
+ /// 2. inst: Index // for every body_len
+ /// 3. has_bits: u32 // for every 16 fields
+ /// - sets of 2 bits:
+ /// 0b0X: whether corresponding field has an align expression
+ /// 0bX0: whether corresponding field has a default expression
+ /// 4. fields: { // for every fields_len
+ /// field_name: u32,
+ /// field_type: Ref,
+ /// align: Ref, // if corresponding bit is set
+ /// default_value: Ref, // if corresponding bit is set
+ /// }
pub const StructDecl = struct {
body_len: u32,
fields_len: u32,
@@ -2398,25 +2398,25 @@ pub const Inst = struct {
};
/// Trailing:
- /// 0. inst: Index // for every body_len
- /// 1. has_bits: u32 // for every 32 fields
- /// - the bit is whether corresponding field has an value expression
- /// 2. fields: { // for every fields_len
- /// field_name: u32,
- /// value: Ref, // if corresponding bit is set
- /// }
- /// 3. decl_bits: u32 // for every 8 decls
+ /// 0. decl_bits: u32 // for every 8 decls
/// - sets of 4 bits:
/// 0b000X: whether corresponding decl is pub
/// 0b00X0: whether corresponding decl is exported
/// 0b0X00: whether corresponding decl has an align expression
/// 0bX000: whether corresponding decl has a linksection expression
- /// 4. decl: { // for every decls_len
+ /// 1. decl: { // for every decls_len
/// name: u32, // null terminated string index
/// value: Index,
/// align: Ref, // if corresponding bit is set
/// link_section: Ref, // if corresponding bit is set
/// }
+ /// 2. inst: Index // for every body_len
+ /// 3. has_bits: u32 // for every 32 fields
+ /// - the bit is whether corresponding field has an value expression
+ /// 4. fields: { // for every fields_len
+ /// field_name: u32,
+ /// value: Ref, // if corresponding bit is set
+ /// }
pub const EnumDecl = struct {
/// Can be `Ref.none`.
tag_type: Ref,
@@ -2426,8 +2426,20 @@ pub const Inst = struct {
};
/// Trailing:
- /// 0. inst: Index // for every body_len
- /// 1. has_bits: u32 // for every 8 fields
+ /// 0. decl_bits: u32 // for every 8 decls
+ /// - sets of 4 bits:
+ /// 0b000X: whether corresponding decl is pub
+ /// 0b00X0: whether corresponding decl is exported
+ /// 0b0X00: whether corresponding decl has an align expression
+ /// 0bX000: whether corresponding decl has a linksection expression
+ /// 1. decl: { // for every decls_len
+ /// name: u32, // null terminated string index
+ /// value: Index,
+ /// align: Ref, // if corresponding bit is set
+ /// link_section: Ref, // if corresponding bit is set
+ /// }
+ /// 2. inst: Index // for every body_len
+ /// 3. has_bits: u32 // for every 8 fields
/// - sets of 4 bits:
/// 0b000X: whether corresponding field has a type expression
/// 0b00X0: whether corresponding field has a align expression
@@ -2437,29 +2449,34 @@ pub const Inst = struct {
/// to indicate whether auto enum tag is enabled.
/// 0 = union(tag_type)
/// 1 = union(enum(tag_type))
- /// 2. fields: { // for every fields_len
+ /// 4. fields: { // for every fields_len
/// field_name: u32, // null terminated string index
/// field_type: Ref, // if corresponding bit is set
/// align: Ref, // if corresponding bit is set
/// tag_value: Ref, // if corresponding bit is set
/// }
- /// 3. decl_bits: u32 // for every 8 decls
+ pub const UnionDecl = struct {
+ /// Can be `Ref.none`.
+ tag_type: Ref,
+ body_len: u32,
+ fields_len: u32,
+ decls_len: u32,
+ };
+
+ /// Trailing:
+ /// 0. decl_bits: u32 // for every 8 decls
/// - sets of 4 bits:
/// 0b000X: whether corresponding decl is pub
/// 0b00X0: whether corresponding decl is exported
/// 0b0X00: whether corresponding decl has an align expression
/// 0bX000: whether corresponding decl has a linksection expression
- /// 4. decl: { // for every decls_len
+ /// 1. decl: { // for every decls_len
/// name: u32, // null terminated string index
/// value: Index,
/// align: Ref, // if corresponding bit is set
/// link_section: Ref, // if corresponding bit is set
/// }
- pub const UnionDecl = struct {
- /// Can be `Ref.none`.
- tag_type: Ref,
- body_len: u32,
- fields_len: u32,
+ pub const OpaqueDecl = struct {
decls_len: u32,
};
@@ -2897,6 +2914,8 @@ const Writer = struct {
.enum_decl_nonexhaustive,
=> try self.writeEnumDecl(stream, inst),
+ .opaque_decl => try self.writeOpaqueDecl(stream, inst),
+
.switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),
.switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),
.switch_block_under => try self.writePlNodeSwitchBr(stream, inst, .under),
@@ -2919,7 +2938,6 @@ const Writer = struct {
.breakpoint,
.fence,
- .opaque_decl,
.dbg_stmt_node,
.repeat,
.repeat_inline,
@@ -3321,27 +3339,45 @@ const Writer = struct {
fn writeStructDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
const extra = self.code.extraData(Inst.StructDecl, 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;
var extra_index: usize = undefined;
+ if (decls_len == 0) {
+ try stream.writeAll("}) ");
+ extra_index = extra.end;
+ } else {
+ try stream.writeAll("\n");
+ self.indent += 2;
+ extra_index = try self.writeDecls(stream, decls_len, extra.end);
+ self.indent -= 2;
+ try stream.writeByteNTimes(' ', self.indent);
+ try stream.writeAll("}) ");
+ }
+
+ const body = self.code.extra[extra_index..][0..extra.data.body_len];
+ extra_index += body.len;
+
if (fields_len == 0) {
assert(body.len == 0);
try stream.writeAll("{}, {}, {");
extra_index = extra.end;
} else {
- try stream.writeAll("{\n");
self.indent += 2;
- try self.writeBody(stream, body);
+ if (body.len == 0) {
+ try stream.writeAll("{}, {\n");
+ } else {
+ try stream.writeAll("{\n");
+ 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, 16) catch unreachable;
- const body_end = extra.end + body.len;
- extra_index = body_end + bit_bags_count;
+ const body_end = extra_index;
+ extra_index += bit_bags_count;
var bit_bag_index: usize = body_end;
var cur_bit_bag: u32 = undefined;
var field_i: u32 = 0;
@@ -3386,27 +3422,30 @@ const Writer = struct {
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("}) ");
- }
try self.writeSrc(stream, inst_data.src());
}
fn writeUnionDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
const extra = self.code.extraData(Inst.UnionDecl, 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_type_ref = extra.data.tag_type;
+ var extra_index: usize = undefined;
+
+ if (decls_len == 0) {
+ try stream.writeAll("{}, ");
+ extra_index = extra.end;
+ } else {
+ try stream.writeAll("{\n");
+ self.indent += 2;
+ extra_index = try self.writeDecls(stream, decls_len, extra.end);
+ self.indent -= 2;
+ try stream.writeByteNTimes(' ', self.indent);
+ try stream.writeAll("}, ");
+ }
+
assert(fields_len != 0);
var first_has_auto_enum: ?bool = null;
@@ -3415,20 +3454,25 @@ const Writer = struct {
try stream.writeAll(", ");
}
- var extra_index: usize = undefined;
+ const body = self.code.extra[extra_index..][0..extra.data.body_len];
+ extra_index += body.len;
- try stream.writeAll("{\n");
self.indent += 2;
- try self.writeBody(stream, body);
+ if (body.len == 0) {
+ try stream.writeAll("{}, {\n");
+ } else {
+ try stream.writeAll("{\n");
+ 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 bits_per_field = 4;
const fields_per_u32 = 32 / bits_per_field;
const bit_bags_count = std.math.divCeil(usize, fields_len, fields_per_u32) catch unreachable;
- const body_end = extra.end + body.len;
- extra_index = body_end + bit_bags_count;
+ const body_end = extra_index;
+ extra_index += bit_bags_count;
var bit_bag_index: usize = body_end;
var cur_bit_bag: u32 = undefined;
var field_i: u32 = 0;
@@ -3482,23 +3526,13 @@ const Writer = struct {
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("}");
- }
+ try stream.writeAll("}");
try self.writeFlag(stream, ", autoenum", first_has_auto_enum.?);
try stream.writeAll(") ");
try self.writeSrc(stream, inst_data.src());
}
- fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !void {
+ fn writeDecls(self: *Writer, stream: anytype, decls_len: u32, extra_start: usize) !usize {
const parent_decl_node = self.parent_decl_node;
const bit_bags_count = std.math.divCeil(usize, decls_len, 8) catch unreachable;
var extra_index = extra_start + bit_bags_count;
@@ -3561,38 +3595,56 @@ const Writer = struct {
try self.writeSrc(stream, decl_block_inst_data.src());
try stream.writeAll("\n");
}
+ return extra_index;
}
fn writeEnumDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
const inst_data = self.code.instructions.items(.data)[inst].pl_node;
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_type_ref = extra.data.tag_type;
+ var extra_index: usize = undefined;
+
+ if (decls_len == 0) {
+ try stream.writeAll("{}, ");
+ extra_index = extra.end;
+ } else {
+ try stream.writeAll("{\n");
+ self.indent += 2;
+ extra_index = try self.writeDecls(stream, decls_len, extra.end);
+ self.indent -= 2;
+ try stream.writeByteNTimes(' ', self.indent);
+ try stream.writeAll("}, ");
+ }
+
if (tag_type_ref != .none) {
try self.writeInstRef(stream, tag_type_ref);
try stream.writeAll(", ");
}
- var extra_index: usize = undefined;
+ const body = self.code.extra[extra_index..][0..extra.data.body_len];
+ extra_index += body.len;
if (fields_len == 0) {
assert(body.len == 0);
- try stream.writeAll("{}, {}, {");
- extra_index = extra.end;
+ try stream.writeAll("{}, {}) ");
} else {
- try stream.writeAll("{\n");
self.indent += 2;
- try self.writeBody(stream, body);
+ if (body.len == 0) {
+ try stream.writeAll("{}, {\n");
+ } else {
+ try stream.writeAll("{\n");
+ 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;
- extra_index = body_end + bit_bags_count;
+ const body_end = extra_index;
+ extra_index += bit_bags_count;
var bit_bag_index: usize = body_end;
var cur_bit_bag: u32 = undefined;
var field_i: u32 = 0;
@@ -3621,14 +3673,22 @@ const Writer = struct {
}
self.indent -= 2;
try stream.writeByteNTimes(' ', self.indent);
- try stream.writeAll("}, {");
+ try stream.writeAll("}) ");
}
+ try self.writeSrc(stream, inst_data.src());
+ }
+
+ fn writeOpaqueDecl(self: *Writer, stream: anytype, inst: Inst.Index) !void {
+ const inst_data = self.code.instructions.items(.data)[inst].pl_node;
+ const extra = self.code.extraData(Inst.OpaqueDecl, inst_data.payload_index);
+ const decls_len = extra.data.decls_len;
+
if (decls_len == 0) {
try stream.writeAll("}) ");
} else {
try stream.writeAll("\n");
self.indent += 2;
- try self.writeDecls(stream, decls_len, extra_index);
+ _ = try self.writeDecls(stream, decls_len, extra.end);
self.indent -= 2;
try stream.writeByteNTimes(' ', self.indent);
try stream.writeAll("}) ");