authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-01 22:34:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-01 22:39:09-07:00
log8ebfdc14f68521ac129ee7d2c3f4e7250e4e7418
tree7a20ca7752b10da7e811a52927b6d1ba0869e893
parentc66b48194ff83eb5b1774a1428461f5fc94dcd7d

stage2: implement structs in the frontend

New ZIR instructions: * struct_decl_packed * struct_decl_extern New TZIR instruction: struct_field_ptr Introduce `Module.Struct`. It uses `Value` to store default values and abi alignments. Implemented Sema.analyzeStructFieldPtr and zirStructDecl. Some stuff I changed from `@panic("TODO")` to `log.warn("TODO")`. It's becoming more clear that we need the lazy value mechanism soon; Type is becoming unruly, and some of these functions have too much logic given that they don't have any context for memory management or error reporting.

8 files changed, 304 insertions(+), 16 deletions(-)

src/AstGen.zig+9-2
......@@ -1322,6 +1322,8 @@ fn blockExprStmts(
13221322 .switch_capture_else_ref,
13231323 .struct_init_empty,
13241324 .struct_decl,
1325 .struct_decl_packed,
1326 .struct_decl_extern,
13251327 .union_decl,
13261328 .enum_decl,
13271329 .opaque_decl,
......@@ -1789,8 +1791,13 @@ fn containerDecl(
17891791
17901792 switch (token_tags[container_decl.ast.main_token]) {
17911793 .keyword_struct => {
1794 const tag = if (container_decl.layout_token) |t| switch (token_tags[t]) {
1795 .keyword_packed => zir.Inst.Tag.struct_decl_packed,
1796 .keyword_extern => zir.Inst.Tag.struct_decl_extern,
1797 else => unreachable,
1798 } else zir.Inst.Tag.struct_decl;
17921799 if (container_decl.ast.members.len == 0) {
1793 const result = try gz.addPlNode(.struct_decl, node, zir.Inst.StructDecl{
1800 const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{
17941801 .fields_len = 0,
17951802 });
17961803 return rvalue(gz, scope, rl, result, node);
......@@ -1856,7 +1863,7 @@ fn containerDecl(
18561863 const empty_slot_count = 16 - ((member_index - 1) % 16);
18571864 cur_bit_bag >>= @intCast(u5, empty_slot_count * 2);
18581865
1859 const result = try gz.addPlNode(.struct_decl, node, zir.Inst.StructDecl{
1866 const result = try gz.addPlNode(tag, node, zir.Inst.StructDecl{
18601867 .fields_len = @intCast(u32, container_decl.ast.members.len),
18611868 });
18621869 try astgen.extra.ensureCapacity(gpa, astgen.extra.items.len +
src/Module.zig+41
......@@ -356,6 +356,25 @@ pub const ErrorSet = struct {
356356 names_ptr: [*]const []const u8,
357357};
358358
359/// Represents the data that a struct declaration provides.
360pub const Struct = struct {
361 owner_decl: *Decl,
362 /// Set of field names in declaration order.
363 fields: std.StringArrayHashMapUnmanaged(Field),
364 /// Represents the declarations inside this struct.
365 container: Scope.Container,
366
367 /// Offset from Decl node index, points to the struct AST node.
368 node_offset: i32,
369
370 pub const Field = struct {
371 ty: Type,
372 abi_align: Value,
373 /// Uses `unreachable_value` to indicate no default.
374 default_val: Value,
375 };
376};
377
359378/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
360379/// Extern functions do not have this data structure; they are represented by
361380/// the `Decl` only, with a `Value` tag of `extern_fn`.
......@@ -822,6 +841,7 @@ pub const Scope = struct {
822841 try block.instructions.append(block.sema.gpa, &inst.base);
823842 return &inst.base;
824843 }
844
825845 pub fn addBr(
826846 scope_block: *Scope.Block,
827847 src: LazySrcLoc,
......@@ -920,6 +940,27 @@ pub const Scope = struct {
920940 try block.instructions.append(block.sema.gpa, &inst.base);
921941 return &inst.base;
922942 }
943
944 pub fn addStructFieldPtr(
945 block: *Scope.Block,
946 src: LazySrcLoc,
947 ty: Type,
948 struct_ptr: *ir.Inst,
949 field_index: u32,
950 ) !*ir.Inst {
951 const inst = try block.sema.arena.create(ir.Inst.StructFieldPtr);
952 inst.* = .{
953 .base = .{
954 .tag = .struct_field_ptr,
955 .ty = ty,
956 .src = src,
957 },
958 .struct_ptr = struct_ptr,
959 .field_index = field_index,
960 };
961 try block.instructions.append(block.sema.gpa, &inst.base);
962 return &inst.base;
963 }
923964 };
924965
925966 /// This is a temporary structure; references to it are valid only
src/Sema.zig+118-10
......@@ -261,7 +261,9 @@ pub fn analyzeBody(
261261 .xor => try sema.zirBitwise(block, inst, .xor),
262262 .struct_init_empty => try sema.zirStructInitEmpty(block, inst),
263263
264 .struct_decl => try sema.zirStructDecl(block, inst),
264 .struct_decl => try sema.zirStructDecl(block, inst, .Auto),
265 .struct_decl_packed => try sema.zirStructDecl(block, inst, .Packed),
266 .struct_decl_extern => try sema.zirStructDecl(block, inst, .Extern),
265267 .enum_decl => try sema.zirEnumDecl(block, inst),
266268 .union_decl => try sema.zirUnionDecl(block, inst),
267269 .opaque_decl => try sema.zirOpaqueDecl(block, inst),
......@@ -520,21 +522,98 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) In
520522 return sema.mod.fail(&block.base, sema.src, "TODO implement zirCoerceResultPtr", .{});
521523}
522524
523fn zirStructDecl(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!*Inst {
525fn zirStructDecl(
526 sema: *Sema,
527 block: *Scope.Block,
528 inst: zir.Inst.Index,
529 layout: std.builtin.TypeInfo.ContainerLayout,
530) InnerError!*Inst {
524531 const tracy = trace(@src());
525532 defer tracy.end();
526533
534 const gpa = sema.gpa;
527535 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
528536 const src = inst_data.src();
529 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
537 const extra = sema.code.extraData(zir.Inst.StructDecl, inst_data.payload_index);
538 const fields_len = extra.data.fields_len;
539 const bit_bags_count = std.math.divCeil(usize, fields_len, 16) catch unreachable;
540
541 var new_decl_arena = std.heap.ArenaAllocator.init(sema.gpa);
542 errdefer new_decl_arena.deinit();
543
544 var fields_map: std.StringArrayHashMapUnmanaged(Module.Struct.Field) = .{};
545 try fields_map.ensureCapacity(&new_decl_arena.allocator, fields_len);
530546
531 return sema.mod.fail(&block.base, sema.src, "TODO implement zirStructDecl", .{});
547 {
548 var field_index: usize = extra.end + bit_bags_count;
549 var bit_bag_index: usize = extra.end;
550 var cur_bit_bag: u32 = undefined;
551 var field_i: u32 = 0;
552 while (field_i < fields_len) : (field_i += 1) {
553 if (field_i % 16 == 0) {
554 cur_bit_bag = sema.code.extra[bit_bag_index];
555 bit_bag_index += 1;
556 }
557 const has_align = @truncate(u1, cur_bit_bag) != 0;
558 cur_bit_bag >>= 1;
559 const has_default = @truncate(u1, cur_bit_bag) != 0;
560 cur_bit_bag >>= 1;
561
562 const field_name_zir = sema.code.nullTerminatedString(sema.code.extra[field_index]);
563 field_index += 1;
564 const field_type_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
565 field_index += 1;
566
567 // This string needs to outlive the ZIR code.
568 const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir);
569 // TODO: if we need to report an error here, use a source location
570 // that points to this type expression rather than the struct.
571 // But only resolve the source location if we need to emit a compile error.
572 const field_ty = try sema.resolveType(block, src, field_type_ref);
573
574 const gop = fields_map.getOrPutAssumeCapacity(field_name);
575 assert(!gop.found_existing);
576 gop.entry.value = .{
577 .ty = field_ty,
578 .abi_align = Value.initTag(.abi_align_default),
579 .default_val = Value.initTag(.unreachable_value),
580 };
581
582 if (has_align) {
583 const align_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
584 field_index += 1;
585 // TODO: if we need to report an error here, use a source location
586 // that points to this alignment expression rather than the struct.
587 // But only resolve the source location if we need to emit a compile error.
588 gop.entry.value.abi_align = (try sema.resolveInstConst(block, src, align_ref)).val;
589 }
590 if (has_default) {
591 const default_ref = @intToEnum(zir.Inst.Ref, sema.code.extra[field_index]);
592 field_index += 1;
593 // TODO: if we need to report an error here, use a source location
594 // that points to this default value expression rather than the struct.
595 // But only resolve the source location if we need to emit a compile error.
596 gop.entry.value.default_val = (try sema.resolveInstConst(block, src, default_ref)).val;
597 }
598 }
599 }
532600
533 //const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{
534 // .ty = decl_ty,
535 // .val = decl_val,
536 //});
537 //return sema.analyzeDeclVal(block, src, new_decl);
601 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
602 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
603 struct_obj.* = .{
604 .owner_decl = sema.owner_decl,
605 .fields = fields_map,
606 .node_offset = inst_data.src_node,
607 .container = .{
608 .ty = struct_ty,
609 .file_scope = block.getFileScope(),
610 },
611 };
612 const new_decl = try sema.mod.createAnonymousDecl(&block.base, &new_decl_arena, .{
613 .ty = Type.initTag(.type),
614 .val = try Value.Tag.ty.create(gpa, struct_ty),
615 });
616 return sema.analyzeDeclVal(block, src, new_decl);
538617}
539618
540619fn 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
763842 const extra = sema.code.extraData(zir.Inst.Block, inst_data.payload_index);
764843 const instrs = sema.code.extra[extra.end..][0..extra.data.body_len];
765844
766 return sema.mod.fail(&block.base, src, "TODO implement zirValidateStructInitPtr", .{});
845 log.warn("TODO implement zirValidateStructInitPtr (compile errors for missing/dupe fields)", .{});
767846}
768847
769848fn zirStoreToBlockPtr(sema: *Sema, block: *Scope.Block, inst: zir.Inst.Index) InnerError!void {
......@@ -4141,11 +4220,40 @@ fn namedFieldPtr(
41414220 else => return sema.mod.fail(&block.base, src, "type '{}' does not support field access", .{child_type}),
41424221 }
41434222 },
4223 .Struct => return sema.analyzeStructFieldPtr(block, src, object_ptr, field_name, field_name_src, elem_ty),
41444224 else => {},
41454225 }
41464226 return sema.mod.fail(&block.base, src, "type '{}' does not support field access", .{elem_ty});
41474227}
41484228
4229fn analyzeStructFieldPtr(
4230 sema: *Sema,
4231 block: *Scope.Block,
4232 src: LazySrcLoc,
4233 struct_ptr: *Inst,
4234 field_name: []const u8,
4235 field_name_src: LazySrcLoc,
4236 elem_ty: Type,
4237) InnerError!*Inst {
4238 const mod = sema.mod;
4239 const arena = sema.arena;
4240 assert(elem_ty.zigTypeTag() == .Struct);
4241
4242 const struct_obj = elem_ty.castTag(.@"struct").?.data;
4243
4244 const field_index = struct_obj.fields.getIndex(field_name) orelse {
4245 // TODO note: struct S declared here
4246 return mod.fail(&block.base, field_name_src, "no field named '{s}' in struct '{}'", .{
4247 field_name, elem_ty,
4248 });
4249 };
4250 const field = struct_obj.fields.entries.items[field_index].value;
4251 const ptr_field_ty = try mod.simplePtrType(arena, field.ty, true, .One);
4252 // TODO comptime field access
4253 try sema.requireRuntimeBlock(block, src);
4254 return block.addStructFieldPtr(src, ptr_field_ty, struct_ptr, @intCast(u32, field_index));
4255}
4256
41494257fn elemPtr(
41504258 sema: *Sema,
41514259 block: *Scope.Block,
src/codegen.zig+5
......@@ -910,6 +910,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
910910 .ret => return self.genRet(inst.castTag(.ret).?),
911911 .retvoid => return self.genRetVoid(inst.castTag(.retvoid).?),
912912 .store => return self.genStore(inst.castTag(.store).?),
913 .struct_field_ptr => return self.genStructFieldPtr(inst.castTag(.struct_field_ptr).?),
913914 .sub => return self.genSub(inst.castTag(.sub).?),
914915 .subwrap => return self.genSubWrap(inst.castTag(.subwrap).?),
915916 .switchbr => return self.genSwitch(inst.castTag(.switchbr).?),
......@@ -1403,6 +1404,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
14031404 return .none;
14041405 }
14051406
1407 fn genStructFieldPtr(self: *Self, inst: *ir.Inst.StructFieldPtr) !MCValue {
1408 return self.fail(inst.base.src, "TODO implement codegen struct_field_ptr", .{});
1409 }
1410
14061411 fn genSub(self: *Self, inst: *ir.Inst.BinOp) !MCValue {
14071412 // No side effects, so if it's unreferenced, do nothing.
14081413 if (inst.base.isUnused())
src/ir.zig+40
......@@ -137,6 +137,8 @@ pub const Inst = struct {
137137 wrap_errunion_err,
138138 xor,
139139 switchbr,
140 /// Given a pointer to a struct and a field index, returns a pointer to the field.
141 struct_field_ptr,
140142
141143 pub fn Type(tag: Tag) type {
142144 return switch (tag) {
......@@ -204,6 +206,7 @@ pub const Inst = struct {
204206 .constant => Constant,
205207 .loop => Loop,
206208 .varptr => VarPtr,
209 .struct_field_ptr => StructFieldPtr,
207210 .switchbr => SwitchBr,
208211 .dbg_stmt => DbgStmt,
209212 };
......@@ -552,6 +555,27 @@ pub const Inst = struct {
552555 }
553556 };
554557
558 pub const StructFieldPtr = struct {
559 pub const base_tag = Tag.struct_field_ptr;
560
561 base: Inst,
562 struct_ptr: *Inst,
563 field_index: usize,
564
565 pub fn operandCount(self: *const StructFieldPtr) usize {
566 return 1;
567 }
568 pub fn getOperand(self: *const StructFieldPtr, index: usize) ?*Inst {
569 var i = index;
570
571 if (i < 1)
572 return self.struct_ptr;
573 i -= 1;
574
575 return null;
576 }
577 };
578
555579 pub const SwitchBr = struct {
556580 pub const base_tag = Tag.switchbr;
557581
......@@ -794,6 +818,10 @@ const DumpTzir = struct {
794818 try dtz.findConst(arg);
795819 }
796820 },
821 .struct_field_ptr => {
822 const struct_field_ptr = inst.castTag(.struct_field_ptr).?;
823 try dtz.findConst(struct_field_ptr.struct_ptr);
824 },
797825
798826 // TODO fill out this debug printing
799827 .assembly,
......@@ -1067,6 +1095,18 @@ const DumpTzir = struct {
10671095 }
10681096 },
10691097
1098 .struct_field_ptr => {
1099 const struct_field_ptr = inst.castTag(.struct_field_ptr).?;
1100 const kinky = try dtz.writeInst(writer, struct_field_ptr.struct_ptr);
1101 if (kinky != null) {
1102 try writer.print("{d}) // Instruction does not dominate all uses!\n", .{
1103 struct_field_ptr.field_index,
1104 });
1105 } else {
1106 try writer.print("{d})\n", .{struct_field_ptr.field_index});
1107 }
1108 },
1109
10701110 // TODO fill out this debug printing
10711111 .assembly,
10721112 .constant,
src/type.zig+63-2
......@@ -4,6 +4,7 @@ const assert = std.debug.assert;
44const Allocator = std.mem.Allocator;
55const Target = std.Target;
66const Module = @import("Module.zig");
7const log = std.log.scoped(.Type);
78
89/// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication.
910/// It's important for this type to be small.
......@@ -94,6 +95,7 @@ pub const Type = extern union {
9495
9596 .empty_struct => return .Struct,
9697 .empty_struct_literal => return .Struct,
98 .@"struct" => return .Struct,
9799
98100 .var_args_param => unreachable, // can be any type
99101 }
......@@ -611,7 +613,7 @@ pub const Type = extern union {
611613 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
612614 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
613615 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
614
616 .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),
615617 .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),
616618 }
617619 }
......@@ -675,6 +677,7 @@ pub const Type = extern union {
675677 .@"undefined" => return out_stream.writeAll("@Type(.Undefined)"),
676678
677679 .empty_struct, .empty_struct_literal => return out_stream.writeAll("struct {}"),
680 .@"struct" => return out_stream.writeAll("(struct)"),
678681 .anyerror_void_error_union => return out_stream.writeAll("anyerror!void"),
679682 .const_slice_u8 => return out_stream.writeAll("[]const u8"),
680683 .fn_noreturn_no_args => return out_stream.writeAll("fn() noreturn"),
......@@ -940,6 +943,18 @@ pub const Type = extern union {
940943 .error_set,
941944 .error_set_single,
942945 => true,
946
947 .@"struct" => {
948 // TODO introduce lazy value mechanism
949 const struct_obj = self.castTag(.@"struct").?.data;
950 for (struct_obj.fields.entries.items) |entry| {
951 if (entry.value.ty.hasCodeGenBits())
952 return true;
953 } else {
954 return false;
955 }
956 },
957
943958 // TODO lazy types
944959 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
945960 .array_u8 => self.arrayLen() != 0,
......@@ -1100,6 +1115,10 @@ pub const Type = extern union {
11001115 @panic("TODO abiAlignment error union");
11011116 },
11021117
1118 .@"struct" => {
1119 @panic("TODO abiAlignment struct");
1120 },
1121
11031122 .c_void,
11041123 .void,
11051124 .type,
......@@ -1144,6 +1163,10 @@ pub const Type = extern union {
11441163 .@"opaque" => unreachable,
11451164 .var_args_param => unreachable,
11461165
1166 .@"struct" => {
1167 @panic("TODO abiSize struct");
1168 },
1169
11471170 .u8,
11481171 .i8,
11491172 .bool,
......@@ -1316,6 +1339,7 @@ pub const Type = extern union {
13161339 .anyerror_void_error_union,
13171340 .error_set,
13181341 .error_set_single,
1342 .@"struct",
13191343 .empty_struct,
13201344 .empty_struct_literal,
13211345 .@"opaque",
......@@ -1393,6 +1417,7 @@ pub const Type = extern union {
13931417 .empty_struct,
13941418 .empty_struct_literal,
13951419 .@"opaque",
1420 .@"struct",
13961421 .var_args_param,
13971422 => unreachable,
13981423
......@@ -1487,6 +1512,7 @@ pub const Type = extern union {
14871512 .empty_struct_literal,
14881513 .inferred_alloc_const,
14891514 .inferred_alloc_mut,
1515 .@"struct",
14901516 .@"opaque",
14911517 .var_args_param,
14921518 => false,
......@@ -1564,6 +1590,7 @@ pub const Type = extern union {
15641590 .empty_struct_literal,
15651591 .inferred_alloc_const,
15661592 .inferred_alloc_mut,
1593 .@"struct",
15671594 .@"opaque",
15681595 .var_args_param,
15691596 => false,
......@@ -1650,6 +1677,7 @@ pub const Type = extern union {
16501677 .empty_struct_literal,
16511678 .inferred_alloc_const,
16521679 .inferred_alloc_mut,
1680 .@"struct",
16531681 .@"opaque",
16541682 .var_args_param,
16551683 => false,
......@@ -1731,6 +1759,7 @@ pub const Type = extern union {
17311759 .empty_struct_literal,
17321760 .inferred_alloc_const,
17331761 .inferred_alloc_mut,
1762 .@"struct",
17341763 .@"opaque",
17351764 .var_args_param,
17361765 => false,
......@@ -1792,7 +1821,11 @@ pub const Type = extern union {
17921821 .ErrorUnion => ty = ty.errorUnionChild(),
17931822
17941823 .Fn => @panic("TODO fn isValidVarType"),
1795 .Struct => @panic("TODO struct isValidVarType"),
1824 .Struct => {
1825 // TODO this is not always correct; introduce lazy value mechanism
1826 // and here we need to force a resolve of "type requires comptime".
1827 return true;
1828 },
17961829 .Union => @panic("TODO union isValidVarType"),
17971830 };
17981831 }
......@@ -1850,6 +1883,7 @@ pub const Type = extern union {
18501883 .anyerror_void_error_union => unreachable,
18511884 .error_set => unreachable,
18521885 .error_set_single => unreachable,
1886 .@"struct" => unreachable,
18531887 .empty_struct => unreachable,
18541888 .empty_struct_literal => unreachable,
18551889 .inferred_alloc_const => unreachable,
......@@ -1999,6 +2033,7 @@ pub const Type = extern union {
19992033 .anyerror_void_error_union,
20002034 .error_set,
20012035 .error_set_single,
2036 .@"struct",
20022037 .empty_struct,
20032038 .empty_struct_literal,
20042039 .inferred_alloc_const,
......@@ -2070,6 +2105,7 @@ pub const Type = extern union {
20702105 .anyerror_void_error_union,
20712106 .error_set,
20722107 .error_set_single,
2108 .@"struct",
20732109 .empty_struct,
20742110 .empty_struct_literal,
20752111 .inferred_alloc_const,
......@@ -2156,6 +2192,7 @@ pub const Type = extern union {
21562192 .anyerror_void_error_union,
21572193 .error_set,
21582194 .error_set_single,
2195 .@"struct",
21592196 .empty_struct,
21602197 .empty_struct_literal,
21612198 .inferred_alloc_const,
......@@ -2238,6 +2275,7 @@ pub const Type = extern union {
22382275 .anyerror_void_error_union,
22392276 .error_set,
22402277 .error_set_single,
2278 .@"struct",
22412279 .empty_struct,
22422280 .empty_struct_literal,
22432281 .inferred_alloc_const,
......@@ -2306,6 +2344,7 @@ pub const Type = extern union {
23062344 .anyerror_void_error_union,
23072345 .error_set,
23082346 .error_set_single,
2347 .@"struct",
23092348 .empty_struct,
23102349 .empty_struct_literal,
23112350 .inferred_alloc_const,
......@@ -2402,6 +2441,7 @@ pub const Type = extern union {
24022441 .anyerror_void_error_union,
24032442 .error_set,
24042443 .error_set_single,
2444 .@"struct",
24052445 .empty_struct,
24062446 .empty_struct_literal,
24072447 .inferred_alloc_const,
......@@ -2519,6 +2559,7 @@ pub const Type = extern union {
25192559 .anyerror_void_error_union,
25202560 .error_set,
25212561 .error_set_single,
2562 .@"struct",
25222563 .empty_struct,
25232564 .empty_struct_literal,
25242565 .inferred_alloc_const,
......@@ -2602,6 +2643,7 @@ pub const Type = extern union {
26022643 .anyerror_void_error_union,
26032644 .error_set,
26042645 .error_set_single,
2646 .@"struct",
26052647 .empty_struct,
26062648 .empty_struct_literal,
26072649 .inferred_alloc_const,
......@@ -2684,6 +2726,7 @@ pub const Type = extern union {
26842726 .anyerror_void_error_union,
26852727 .error_set,
26862728 .error_set_single,
2729 .@"struct",
26872730 .empty_struct,
26882731 .empty_struct_literal,
26892732 .inferred_alloc_const,
......@@ -2766,6 +2809,7 @@ pub const Type = extern union {
27662809 .anyerror_void_error_union,
27672810 .error_set,
27682811 .error_set_single,
2812 .@"struct",
27692813 .empty_struct,
27702814 .empty_struct_literal,
27712815 .inferred_alloc_const,
......@@ -2845,6 +2889,7 @@ pub const Type = extern union {
28452889 .anyerror_void_error_union,
28462890 .error_set,
28472891 .error_set_single,
2892 .@"struct",
28482893 .empty_struct,
28492894 .empty_struct_literal,
28502895 .inferred_alloc_const,
......@@ -2924,6 +2969,7 @@ pub const Type = extern union {
29242969 .anyerror_void_error_union,
29252970 .error_set,
29262971 .error_set_single,
2972 .@"struct",
29272973 .empty_struct,
29282974 .empty_struct_literal,
29292975 .inferred_alloc_const,
......@@ -3003,6 +3049,7 @@ pub const Type = extern union {
30033049 .anyerror_void_error_union,
30043050 .error_set,
30053051 .error_set_single,
3052 .@"struct",
30063053 .empty_struct,
30073054 .empty_struct_literal,
30083055 .inferred_alloc_const,
......@@ -3070,6 +3117,11 @@ pub const Type = extern union {
30703117 .var_args_param,
30713118 => return null,
30723119
3120 .@"struct" => {
3121 log.warn("TODO implement Type.onePossibleValue for structs", .{});
3122 return null;
3123 },
3124
30733125 .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
30743126 .void => return Value.initTag(.void_value),
30753127 .noreturn => return Value.initTag(.unreachable_value),
......@@ -3172,6 +3224,7 @@ pub const Type = extern union {
31723224 .anyerror_void_error_union,
31733225 .error_set,
31743226 .error_set_single,
3227 .@"struct",
31753228 .empty_struct,
31763229 .empty_struct_literal,
31773230 .inferred_alloc_const,
......@@ -3269,6 +3322,7 @@ pub const Type = extern union {
32693322 .empty_struct_literal,
32703323 => unreachable,
32713324
3325 .@"struct" => &self.castTag(.@"struct").?.data.container,
32723326 .empty_struct => self.castTag(.empty_struct).?.data,
32733327 .@"opaque" => &self.castTag(.@"opaque").?.data,
32743328 };
......@@ -3421,6 +3475,7 @@ pub const Type = extern union {
34213475 error_set_single,
34223476 empty_struct,
34233477 @"opaque",
3478 @"struct",
34243479
34253480 pub const last_no_payload_tag = Tag.inferred_alloc_const;
34263481 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -3506,6 +3561,7 @@ pub const Type = extern union {
35063561 .error_union => Payload.ErrorUnion,
35073562 .error_set_single => Payload.Name,
35083563 .@"opaque" => Payload.Opaque,
3564 .@"struct" => Payload.Struct,
35093565 .empty_struct => Payload.ContainerScope,
35103566 };
35113567 }
......@@ -3638,6 +3694,11 @@ pub const Type = extern union {
36383694 base: Payload = .{ .tag = .@"opaque" },
36393695 data: Module.Scope.Container,
36403696 };
3697
3698 pub const Struct = struct {
3699 base: Payload = .{ .tag = .@"struct" },
3700 data: *Module.Struct,
3701 };
36413702 };
36423703};
36433704
src/value.zig+18-1
......@@ -74,6 +74,7 @@ pub const Value = extern union {
7474 bool_true,
7575 bool_false,
7676
77 abi_align_default,
7778 empty_struct_value,
7879 empty_array, // See last_no_payload_tag below.
7980 // After this, the tag requires a payload.
......@@ -165,6 +166,7 @@ pub const Value = extern union {
165166 .null_value,
166167 .bool_true,
167168 .bool_false,
169 .abi_align_default,
168170 => @compileError("Value Tag " ++ @tagName(t) ++ " has no payload"),
169171
170172 .int_big_positive,
......@@ -320,6 +322,7 @@ pub const Value = extern union {
320322 .bool_true,
321323 .bool_false,
322324 .empty_struct_value,
325 .abi_align_default,
323326 => unreachable,
324327
325328 .ty => {
......@@ -464,8 +467,8 @@ pub const Value = extern union {
464467 .single_const_pointer_to_comptime_int_type => return out_stream.writeAll("*const comptime_int"),
465468 .const_slice_u8_type => return out_stream.writeAll("[]const u8"),
466469 .enum_literal_type => return out_stream.writeAll("@Type(.EnumLiteral)"),
470 .abi_align_default => return out_stream.writeAll("(default ABI alignment)"),
467471
468 // TODO this should print `NAME{}`
469472 .empty_struct_value => return out_stream.writeAll("struct {}{}"),
470473 .null_value => return out_stream.writeAll("null"),
471474 .undef => return out_stream.writeAll("undefined"),
......@@ -627,6 +630,7 @@ pub const Value = extern union {
627630 .error_union,
628631 .empty_struct_value,
629632 .inferred_alloc,
633 .abi_align_default,
630634 => unreachable,
631635 };
632636 }
......@@ -699,6 +703,7 @@ pub const Value = extern union {
699703 .@"error",
700704 .empty_struct_value,
701705 .inferred_alloc,
706 .abi_align_default,
702707 => unreachable,
703708
704709 .undef => unreachable,
......@@ -786,6 +791,7 @@ pub const Value = extern union {
786791 .error_union,
787792 .empty_struct_value,
788793 .inferred_alloc,
794 .abi_align_default,
789795 => unreachable,
790796
791797 .undef => unreachable,
......@@ -873,6 +879,7 @@ pub const Value = extern union {
873879 .error_union,
874880 .empty_struct_value,
875881 .inferred_alloc,
882 .abi_align_default,
876883 => unreachable,
877884
878885 .undef => unreachable,
......@@ -988,6 +995,7 @@ pub const Value = extern union {
988995 .error_union,
989996 .empty_struct_value,
990997 .inferred_alloc,
998 .abi_align_default,
991999 => unreachable,
9921000
9931001 .zero,
......@@ -1079,6 +1087,7 @@ pub const Value = extern union {
10791087 .error_union,
10801088 .empty_struct_value,
10811089 .inferred_alloc,
1090 .abi_align_default,
10821091 => unreachable,
10831092
10841093 .zero,
......@@ -1239,6 +1248,7 @@ pub const Value = extern union {
12391248 .error_union,
12401249 .empty_struct_value,
12411250 .inferred_alloc,
1251 .abi_align_default,
12421252 => unreachable,
12431253
12441254 .zero,
......@@ -1317,6 +1327,7 @@ pub const Value = extern union {
13171327 .error_union,
13181328 .empty_struct_value,
13191329 .inferred_alloc,
1330 .abi_align_default,
13201331 => unreachable,
13211332
13221333 .zero,
......@@ -1452,6 +1463,7 @@ pub const Value = extern union {
14521463 .const_slice_u8_type,
14531464 .enum_literal_type,
14541465 .ty,
1466 .abi_align_default,
14551467 => {
14561468 // Directly return Type.hash, toType can only fail for .int_type.
14571469 var allocator = std.heap.FixedBufferAllocator.init(&[_]u8{});
......@@ -1632,6 +1644,7 @@ pub const Value = extern union {
16321644 .error_union,
16331645 .empty_struct_value,
16341646 .inferred_alloc,
1647 .abi_align_default,
16351648 => unreachable,
16361649
16371650 .ref_val => self.castTag(.ref_val).?.data,
......@@ -1719,6 +1732,7 @@ pub const Value = extern union {
17191732 .error_union,
17201733 .empty_struct_value,
17211734 .inferred_alloc,
1735 .abi_align_default,
17221736 => unreachable,
17231737
17241738 .empty_array => unreachable, // out of bounds array index
......@@ -1822,6 +1836,7 @@ pub const Value = extern union {
18221836 .@"error",
18231837 .error_union,
18241838 .empty_struct_value,
1839 .abi_align_default,
18251840 => false,
18261841
18271842 .undef => unreachable,
......@@ -1903,6 +1918,7 @@ pub const Value = extern union {
19031918 .void_value,
19041919 .enum_literal,
19051920 .empty_struct_value,
1921 .abi_align_default,
19061922 => null,
19071923
19081924 .error_union => {
......@@ -2009,6 +2025,7 @@ pub const Value = extern union {
20092025 .error_union,
20102026 .empty_struct_value,
20112027 .null_value,
2028 .abi_align_default,
20122029 => false,
20132030
20142031 .undef => unreachable,
src/zir.zig+10-1
......@@ -274,6 +274,10 @@ pub const Inst = struct {
274274 /// the field types, defaults, and alignments.
275275 /// Uses the `pl_node` union field. Payload is `StructDecl`.
276276 struct_decl,
277 /// Same as `struct_decl`, except has the `packed` layout.
278 struct_decl_packed,
279 /// Same as `struct_decl`, except has the `extern` layout.
280 struct_decl_extern,
277281 /// A union type definition. Contains references to ZIR instructions for
278282 /// the field types and optional type tag expression.
279283 /// Uses the `pl_node` union field. Payload is `UnionDecl`.
......@@ -707,6 +711,8 @@ pub const Inst = struct {
707711 .coerce_result_ptr,
708712 .@"const",
709713 .struct_decl,
714 .struct_decl_packed,
715 .struct_decl_extern,
710716 .union_decl,
711717 .enum_decl,
712718 .opaque_decl,
......@@ -1655,7 +1661,10 @@ const Writer = struct {
16551661 .condbr_inline,
16561662 => try self.writePlNodeCondBr(stream, inst),
16571663
1658 .struct_decl => try self.writeStructDecl(stream, inst),
1664 .struct_decl,
1665 .struct_decl_packed,
1666 .struct_decl_extern,
1667 => try self.writeStructDecl(stream, inst),
16591668
16601669 .switch_block => try self.writePlNodeSwitchBr(stream, inst, .none),
16611670 .switch_block_else => try self.writePlNodeSwitchBr(stream, inst, .@"else"),