Commit 8ebfdc14f6
Changed files (8)
src/AstGen.zig
@@ -1322,6 +1322,8 @@ fn blockExprStmts(
.switch_capture_else_ref,
.struct_init_empty,
.struct_decl,
+ .struct_decl_packed,
+ .struct_decl_extern,
.union_decl,
.enum_decl,
.opaque_decl,
@@ -1789,8 +1791,13 @@ fn containerDecl(
switch (token_tags[container_decl.ast.main_token]) {
.keyword_struct => {
+ const tag = if (container_decl.layout_token) |t| switch (token_tags[t]) {
+ .keyword_packed => zir.Inst.Tag.struct_decl_packed,
+ .keyword_extern => zir.Inst.Tag.struct_decl_extern,
+ else => unreachable,
+ } else zir.Inst.Tag.struct_decl;
if (container_decl.ast.members.len == 0) {
- const result = try gz.addPlNode(.struct_decl, node, zir.Inst.StructDecl{
+ const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{
.fields_len = 0,
});
return rvalue(gz, scope, rl, result, node);
@@ -1856,7 +1863,7 @@ fn containerDecl(
const empty_slot_count = 16 - ((member_index - 1) % 16);
cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
- const result = try gz.addPlNode(.struct_decl, node, zir.Inst.StructDecl{
+ const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{
.fields_len = @intCast(u32, container_decl.ast.members.len),
});
try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
src/codegen.zig
@@ -910,6 +910,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.ret => return self.genRet(inst.castTag(.ret).?),
.retvoid => return self.genRetVoid(inst.castTag(.retvoid).?),
.store => return self.genStore(inst.castTag(.store).?),
+ .struct_field_ptr => return self.genStructFieldPtr(inst.castTag(.struct_field_ptr).?),
.sub => return self.genSub(inst.castTag(.sub).?),
.subwrap => return self.genSubWrap(inst.castTag(.subwrap).?),
.switchbr => return self.genSwitch(inst.castTag(.switchbr).?),
@@ -1403,6 +1404,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
return .none;
}
+ fn genStructFieldPtr(self: *Self, inst: *ir.Inst.StructFieldPtr) !MCValue {
+ return self.fail(inst.base.src, "TODO implement codegen struct_field_ptr", .{});
+ }
+
fn genSub(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
// No side effects, so if it's unreferenced, do nothing.
if (inst.base.isUnused())
src/ir.zig
@@ -137,6 +137,8 @@ pub const Inst = struct {
wrap_errunion_err,
xor,
switchbr,
+ /// Given a pointer to a struct and a field index, returns a pointer to the field.
+ struct_field_ptr,
pub fn Type(tag: Tag) type {
return switch (tag) {
@@ -204,6 +206,7 @@ pub const Inst = struct {
.constant => Constant,
.loop => Loop,
.varptr => VarPtr,
+ .struct_field_ptr => StructFieldPtr,
.switchbr => SwitchBr,
.dbg_stmt => DbgStmt,
};
@@ -552,6 +555,27 @@ pub const Inst = struct {
}
};
+ pub const StructFieldPtr = struct {
+ pub const base_tag = Tag.struct_field_ptr;
+
+ base: Inst,
+ struct_ptr: *Inst,
+ field_index: usize,
+
+ pub fn operandCount(self: *const StructFieldPtr) usize {
+ return 1;
+ }
+ pub fn getOperand(self: *const StructFieldPtr, index: usize) ?*Inst {
+ var i = index;
+
+ if (i < 1)
+ return self.struct_ptr;
+ i -= 1;
+
+ return null;
+ }
+ };
+
pub const SwitchBr = struct {
pub const base_tag = Tag.switchbr;
@@ -794,6 +818,10 @@ const DumpTzir = struct {
try dtz.findConst(arg);
}
},
+ .struct_field_ptr => {
+ const struct_field_ptr = inst.castTag(.struct_field_ptr).?;
+ try dtz.findConst(struct_field_ptr.struct_ptr);
+ },
// TODO fill out this debug printing
.assembly,
@@ -1067,6 +1095,18 @@ const DumpTzir = struct {
}
},
+ .struct_field_ptr => {
+ const struct_field_ptr = inst.castTag(.struct_field_ptr).?;
+ const kinky = try dtz.writeInst(writer, struct_field_ptr.struct_ptr);
+ if (kinky != null) {
+ try writer.print("{d}) // Instruction does not dominate all uses!\n", .{
+ struct_field_ptr.field_index,
+ });
+ } else {
+ try writer.print("{d})\n", .{struct_field_ptr.field_index});
+ }
+ },
+
// TODO fill out this debug printing
.assembly,
.constant,
src/Module.zig
@@ -356,6 +356,25 @@ pub const ErrorSet = struct {
names_ptr: [*]const []const u8,
};
+/// Represents the data that a struct declaration provides.
+pub const Struct = struct {
+ owner_decl: *Decl,
+ /// Set of field names in declaration order.
+ fields: std.StringArrayHashMapUnmanaged(Field),
+ /// Represents the declarations inside this struct.
+ container: Scope.Container,
+
+ /// Offset from Decl node index, points to the struct AST node.
+ node_offset: i32,
+
+ pub const Field = struct {
+ ty: Type,
+ abi_align: Value,
+ /// Uses `unreachable_value` to indicate no default.
+ default_val: Value,
+ };
+};
+
/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
/// Extern functions do not have this data structure; they are represented by
/// the `Decl` only, with a `Value` tag of `extern_fn`.
@@ -822,6 +841,7 @@ pub const Scope = struct {
try block.instructions.append(block.sema.gpa, &inst.base);
return &inst.base;
}
+
pub fn addBr(
scope_block: *Scope.Block,
src: LazySrcLoc,
@@ -920,6 +940,27 @@ pub const Scope = struct {
try block.instructions.append(block.sema.gpa, &inst.base);
return &inst.base;
}
+
+ pub fn addStructFieldPtr(
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ ty: Type,
+ struct_ptr: *ir.Inst,
+ field_index: u32,
+ ) !*ir.Inst {
+ const inst = try block.sema.arena.create(ir.Inst.StructFieldPtr);
+ inst.* = .{
+ .base = .{
+ .tag = .struct_field_ptr,
+ .ty = ty,
+ .src = src,
+ },
+ .struct_ptr = struct_ptr,
+ .field_index = field_index,
+ };
+ try block.instructions.append(block.sema.gpa, &inst.base);
+ return &inst.base;
+ }
};
/// This is a temporary structure; references to it are valid only
src/Sema.zig
@@ -261,7 +261,9 @@ pub fn analyzeBody(
.xor => try sema.zirBitwise(block, inst, .xor),
.struct_init_empty => try sema.zirStructInitEmpty(block, inst),
- .struct_decl => try sema.zirStructDecl(block, inst),
+ .struct_decl => try sema.zirStructDecl(block, inst, .Auto),
+ .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
+ .struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),
.enum_decl => try sema.zirEnumDecl(block, inst),
.union_decl => try sema.zirUnionDecl(block, inst),
.opaque_decl => try sema.zirOpaqueDecl(block, inst),
@@ -520,21 +522,98 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});
}
-fn zirStructDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
+fn zirStructDecl(
+ sema: *Sema,
+ block: *Scope.Block,
+ inst: zir.Inst.Index,
+ layout: std.builtin.TypeInfo.ContainerLayout,
+) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
+ const gpa = sema.gpa;
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
- const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
+ const extra = sema.code.extraData(zir.Inst.StructDecl, inst_data.payload_index);
+ const fields_len = extra.data.fields_len;
+ const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;
+
+ var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
+ errdefer new_decl_arena.deinit();
+
+ var fields_map: std.StringArrayHashMapUnmanaged(Module.Struct.Field) = .{};
+ try fields_map.ensureCapacity(&new_decl_arena.allocator, fields_len);
- return sema.mod.fail(&block.base, sema.src, "TODO implement zirStructDecl", .{});
+ {
+ var field_index: usize = extra.end + bit_bags_count;
+ var bit_bag_index: usize = extra.end;
+ var cur_bit_bag: u32 = undefined;
+ var field_i: u32 = 0;
+ while (field_i < fields_len) : (field_i += 1) {
+ if (field_i % 16 == 0) {
+ cur_bit_bag = sema.code.extra[bit_bag_index];
+ bit_bag_index += 1;
+ }
+ const has_align = @truncate(u1, cur_bit_bag) != 0;
+ cur_bit_bag >>= 1;
+ const has_default = @truncate(u1, cur_bit_bag) != 0;
+ cur_bit_bag >>= 1;
+
+ const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[field_index]);
+ field_index += 1;
+ const field_type_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
+ field_index += 1;
+
+ // This string needs to outlive the ZIR code.
+ const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir);
+ // TODO: if we need to report an error here, use a source location
+ // that points to this type expression rather than the struct.
+ // But only resolve the source location if we need to emit a compile error.
+ const field_ty = try sema.resolveType(block, src, field_type_ref);
+
+ const gop = fields_map.getOrPutAssumeCapacity(field_name);
+ assert(!gop.found_existing);
+ gop.entry.value = .{
+ .ty = field_ty,
+ .abi_align = Value.initTag(.abi_align_default),
+ .default_val = Value.initTag(.unreachable_value),
+ };
+
+ if (has_align) {
+ const align_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
+ field_index += 1;
+ // TODO: if we need to report an error here, use a source location
+ // that points to this alignment expression rather than the struct.
+ // But only resolve the source location if we need to emit a compile error.
+ gop.entry.value.abi_align = (try sema.resolveInstConst(block, src, align_ref)).val;
+ }
+ if (has_default) {
+ const default_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
+ field_index += 1;
+ // TODO: if we need to report an error here, use a source location
+ // that points to this default value expression rather than the struct.
+ // But only resolve the source location if we need to emit a compile error.
+ gop.entry.value.default_val = (try sema.resolveInstConst(block, src, default_ref)).val;
+ }
+ }
+ }
- //const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{
- // .ty = decl_ty,
- // .val = decl_val,
- //});
- //return sema.analyzeDeclVal(block, src, new_decl);
+ const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
+ const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
+ struct_obj.* = .{
+ .owner_decl = sema.owner_decl,
+ .fields = fields_map,
+ .node_offset = inst_data.src_node,
+ .container = .{
+ .ty = struct_ty,
+ .file_scope = block.getFileScope(),
+ },
+ };
+ const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{
+ .ty = Type.initTag(.type),
+ .val = try Value.Tag.ty.create(gpa, struct_ty),
+ });
+ return sema.analyzeDeclVal(block, src, new_decl);
}
fn zirEnumDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
@@ -763,7 +842,7 @@ fn zirValidateStructInitPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Ind
const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
const instrs = sema.code.extra[extra.end..][0..extra.data.body_len];
- return sema.mod.fail(&block.base, src, "TODO implement zirValidateStructInitPtr", .{});
+ log.warn("TODO implement zirValidateStructInitPtr (compile errors for missing/dupe fields)", .{});
}
fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
@@ -4141,11 +4220,40 @@ fn namedFieldPtr(
else => return sema.mod.fail(&block.base, src, "type '{}' does not support field access", .{child_type}),
}
},
+ .Struct => return sema.analyzeStructFieldPtr(block, src, object_ptr, field_name, field_name_src, elem_ty),
else => {},
}
return sema.mod.fail(&block.base, src, "type '{}' does not support field access", .{elem_ty});
}
+fn analyzeStructFieldPtr(
+ sema: *Sema,
+ block: *Scope.Block,
+ src: LazySrcLoc,
+ struct_ptr: *Inst,
+ field_name: []const u8,
+ field_name_src: LazySrcLoc,
+ elem_ty: Type,
+) InnerError!*Inst {
+ const mod = sema.mod;
+ const arena = sema.arena;
+ assert(elem_ty.zigTypeTag() == .Struct);
+
+ const struct_obj = elem_ty.castTag(.@"struct").?.data;
+
+ const field_index = struct_obj.fields.getIndex(field_name) orelse {
+ // TODO note: struct S declared here
+ return mod.fail(&block.base, field_name_src, "no field named '{s}' in struct '{}'", .{
+ field_name, elem_ty,
+ });
+ };
+ const field = struct_obj.fields.entries.items[field_index].value;
+ const ptr_field_ty = try mod.simplePtrType(arena, field.ty, true, .One);
+ // TODO comptime field access
+ try sema.requireRuntimeBlock(block, src);
+ return block.addStructFieldPtr(src, ptr_field_ty, struct_ptr, @intCast(u32, field_index));
+}
+
fn elemPtr(
sema: *Sema,
block: *Scope.Block,
src/type.zig
@@ -4,6 +4,7 @@ const assert = std.debug.assert;
const Allocator = std.mem.Allocator;
const Target = std.Target;
const Module = @import("Module.zig");
+const log = std.log.scoped(.Type);
/// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication.
/// It's important for this type to be small.
@@ -94,6 +95,7 @@ pub const Type = extern union {
.empty_struct => return .Struct,
.empty_struct_literal => return .Struct,
+ .@"struct" => return .Struct,
.var_args_param => unreachable, // can be any type
}
@@ -611,7 +613,7 @@ pub const Type = extern union {
.error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
.error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
.empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
-
+ .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),
.@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),
}
}
@@ -675,6 +677,7 @@ pub const Type = extern union {
.@"undefined" => return out_stream.writeAll("@Type(.Undefined)"),
.empty_struct, .empty_struct_literal => return out_stream.writeAll("struct {}"),
+ .@"struct" => return out_stream.writeAll("(struct)"),
.anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),
.const_slice_u8 => return out_stream.writeAll("[]const u8"),
.fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),
@@ -940,6 +943,18 @@ pub const Type = extern union {
.error_set,
.error_set_single,
=> true,
+
+ .@"struct" => {
+ // TODO introduce lazy value mechanism
+ const struct_obj = self.castTag(.@"struct").?.data;
+ for (struct_obj.fields.entries.items) |entry| {
+ if (entry.value.ty.hasCodeGenBits())
+ return true;
+ } else {
+ return false;
+ }
+ },
+
// TODO lazy types
.array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
.array_u8 => self.arrayLen() != 0,
@@ -1100,6 +1115,10 @@ pub const Type = extern union {
@panic("TODO abiAlignment error union");
},
+ .@"struct" => {
+ @panic("TODO abiAlignment struct");
+ },
+
.c_void,
.void,
.type,
@@ -1144,6 +1163,10 @@ pub const Type = extern union {
.@"opaque" => unreachable,
.var_args_param => unreachable,
+ .@"struct" => {
+ @panic("TODO abiSize struct");
+ },
+
.u8,
.i8,
.bool,
@@ -1316,6 +1339,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.@"opaque",
@@ -1393,6 +1417,7 @@ pub const Type = extern union {
.empty_struct,
.empty_struct_literal,
.@"opaque",
+ .@"struct",
.var_args_param,
=> unreachable,
@@ -1487,6 +1512,7 @@ pub const Type = extern union {
.empty_struct_literal,
.inferred_alloc_const,
.inferred_alloc_mut,
+ .@"struct",
.@"opaque",
.var_args_param,
=> false,
@@ -1564,6 +1590,7 @@ pub const Type = extern union {
.empty_struct_literal,
.inferred_alloc_const,
.inferred_alloc_mut,
+ .@"struct",
.@"opaque",
.var_args_param,
=> false,
@@ -1650,6 +1677,7 @@ pub const Type = extern union {
.empty_struct_literal,
.inferred_alloc_const,
.inferred_alloc_mut,
+ .@"struct",
.@"opaque",
.var_args_param,
=> false,
@@ -1731,6 +1759,7 @@ pub const Type = extern union {
.empty_struct_literal,
.inferred_alloc_const,
.inferred_alloc_mut,
+ .@"struct",
.@"opaque",
.var_args_param,
=> false,
@@ -1792,7 +1821,11 @@ pub const Type = extern union {
.ErrorUnion => ty = ty.errorUnionChild(),
.Fn => @panic("TODO fn isValidVarType"),
- .Struct => @panic("TODO struct isValidVarType"),
+ .Struct => {
+ // TODO this is not always correct; introduce lazy value mechanism
+ // and here we need to force a resolve of "type requires comptime".
+ return true;
+ },
.Union => @panic("TODO union isValidVarType"),
};
}
@@ -1850,6 +1883,7 @@ pub const Type = extern union {
.anyerror_void_error_union => unreachable,
.error_set => unreachable,
.error_set_single => unreachable,
+ .@"struct" => unreachable,
.empty_struct => unreachable,
.empty_struct_literal => unreachable,
.inferred_alloc_const => unreachable,
@@ -1999,6 +2033,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2070,6 +2105,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2156,6 +2192,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2238,6 +2275,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2306,6 +2344,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2402,6 +2441,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2519,6 +2559,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2602,6 +2643,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2684,6 +2726,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2766,6 +2809,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2845,6 +2889,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -2924,6 +2969,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -3003,6 +3049,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -3070,6 +3117,11 @@ pub const Type = extern union {
.var_args_param,
=> return null,
+ .@"struct" => {
+ log.warn("TODO implement Type.onePossibleValue for structs", .{});
+ return null;
+ },
+
.empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
.void => return Value.initTag(.void_value),
.noreturn => return Value.initTag(.unreachable_value),
@@ -3172,6 +3224,7 @@ pub const Type = extern union {
.anyerror_void_error_union,
.error_set,
.error_set_single,
+ .@"struct",
.empty_struct,
.empty_struct_literal,
.inferred_alloc_const,
@@ -3269,6 +3322,7 @@ pub const Type = extern union {
.empty_struct_literal,
=> unreachable,
+ .@"struct" => &self.castTag(.@"struct").?.data.container,
.empty_struct => self.castTag(.empty_struct).?.data,
.@"opaque" => &self.castTag(.@"opaque").?.data,
};
@@ -3421,6 +3475,7 @@ pub const Type = extern union {
error_set_single,
empty_struct,
@"opaque",
+ @"struct",
pub const last_no_payload_tag = Tag.inferred_alloc_const;
pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
@@ -3506,6 +3561,7 @@ pub const Type = extern union {
.error_union => Payload.ErrorUnion,
.error_set_single => Payload.Name,
.@"opaque" => Payload.Opaque,
+ .@"struct" => Payload.Struct,
.empty_struct => Payload.ContainerScope,
};
}
@@ -3638,6 +3694,11 @@ pub const Type = extern union {
base: Payload = .{ .tag = .@"opaque" },
data: Module.Scope.Container,
};
+
+ pub const Struct = struct {
+ base: Payload = .{ .tag = .@"struct" },
+ data: *Module.Struct,
+ };
};
};
src/value.zig
@@ -74,6 +74,7 @@ pub const Value = extern union {
bool_true,
bool_false,
+ abi_align_default,
empty_struct_value,
empty_array, // See last_no_payload_tag below.
// After this, the tag requires a payload.
@@ -165,6 +166,7 @@ pub const Value = extern union {
.null_value,
.bool_true,
.bool_false,
+ .abi_align_default,
=> @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
.int_big_positive,
@@ -320,6 +322,7 @@ pub const Value = extern union {
.bool_true,
.bool_false,
.empty_struct_value,
+ .abi_align_default,
=> unreachable,
.ty => {
@@ -464,8 +467,8 @@ pub const Value = extern union {
.single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
.const_slice_u8_type => return out_stream.writeAll("[]const u8"),
.enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
+ .abi_align_default => return out_stream.writeAll("(default ABI alignment)"),
- // TODO this should print `NAME{}`
.empty_struct_value => return out_stream.writeAll("struct {}{}"),
.null_value => return out_stream.writeAll("null"),
.undef => return out_stream.writeAll("undefined"),
@@ -627,6 +630,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
};
}
@@ -699,6 +703,7 @@ pub const Value = extern union {
.@"error",
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.undef => unreachable,
@@ -786,6 +791,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.undef => unreachable,
@@ -873,6 +879,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.undef => unreachable,
@@ -988,6 +995,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.zero,
@@ -1079,6 +1087,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.zero,
@@ -1239,6 +1248,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.zero,
@@ -1317,6 +1327,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.zero,
@@ -1452,6 +1463,7 @@ pub const Value = extern union {
.const_slice_u8_type,
.enum_literal_type,
.ty,
+ .abi_align_default,
=> {
// Directly return Type.hash, toType can only fail for .int_type.
var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{});
@@ -1632,6 +1644,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.ref_val => self.castTag(.ref_val).?.data,
@@ -1719,6 +1732,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.inferred_alloc,
+ .abi_align_default,
=> unreachable,
.empty_array => unreachable, // out of bounds array index
@@ -1822,6 +1836,7 @@ pub const Value = extern union {
.@"error",
.error_union,
.empty_struct_value,
+ .abi_align_default,
=> false,
.undef => unreachable,
@@ -1903,6 +1918,7 @@ pub const Value = extern union {
.void_value,
.enum_literal,
.empty_struct_value,
+ .abi_align_default,
=> null,
.error_union => {
@@ -2009,6 +2025,7 @@ pub const Value = extern union {
.error_union,
.empty_struct_value,
.null_value,
+ .abi_align_default,
=> false,
.undef => unreachable,
src/zir.zig
@@ -274,6 +274,10 @@ pub const Inst = struct {
/// the field types, defaults, and alignments.
/// Uses the `pl_node` union field. Payload is `StructDecl`.
struct_decl,
+ /// Same as `struct_decl`, except has the `packed` layout.
+ struct_decl_packed,
+ /// Same as `struct_decl`, except has the `extern` layout.
+ struct_decl_extern,
/// A union type definition. Contains references to ZIR instructions for
/// the field types and optional type tag expression.
/// Uses the `pl_node` union field. Payload is `UnionDecl`.
@@ -707,6 +711,8 @@ pub const Inst = struct {
.coerce_result_ptr,
.@"const",
.struct_decl,
+ .struct_decl_packed,
+ .struct_decl_extern,
.union_decl,
.enum_decl,
.opaque_decl,
@@ -1655,7 +1661,10 @@ const Writer = struct {
.condbr_inline,
=> try self.writePlNodeCondBr(stream, inst),
- .struct_decl => try self.writeStructDecl(stream, inst),
+ .struct_decl,
+ .struct_decl_packed,
+ .struct_decl_extern,
+ => try self.writeStructDecl(stream, inst),
.switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),
.switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),