authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-11 16:20:32-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-11 16:25:21-07:00
log29c9d5896c0f3349b37eff4cbce280fffa7e2924
tree82aebe8095bc7dcafc6cca525b14ab82c5382278
parent5cc2e500e68a60cb99b48755af39856ff60198b6
parentbace1181b2f6d63e51b6e511aa8318481e2eafee

Merge branch 'Stage2 begin implementing container types'


9 files changed, 647 insertions(+), 11 deletions(-)

src/Module.zig+48-6
......@@ -460,7 +460,7 @@ pub const Scope = struct {
460460 };
461461 }
462462
463 /// Asserts the scope has a parent which is a ZIRModule, Contaienr or File and
463 /// Asserts the scope has a parent which is a ZIRModule, Container or File and
464464 /// returns the sub_file_path field.
465465 pub fn subFilePath(base: *Scope) []const u8 {
466466 switch (base.tag) {
......@@ -501,12 +501,12 @@ pub const Scope = struct {
501501 }
502502 }
503503
504 pub fn getOwnerPkg(base: *Scope) *Package {
504 pub fn getFileScope(base: *Scope) *Scope.File {
505505 var cur = base;
506506 while (true) {
507507 cur = switch (cur.tag) {
508 .container => return @fieldParentPtr(Container, "base", cur).file_scope.pkg,
509 .file => return @fieldParentPtr(File, "base", cur).pkg,
508 .container => return @fieldParentPtr(Container, "base", cur).file_scope,
509 .file => return @fieldParentPtr(File, "base", cur),
510510 .zir_module => unreachable, // TODO are zir modules allowed to import packages?
511511 .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent,
512512 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
......@@ -582,7 +582,7 @@ pub const Scope = struct {
582582 file_scope: *Scope.File,
583583
584584 /// Direct children of the file.
585 decls: std.AutoArrayHashMapUnmanaged(*Decl, void),
585 decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
586586 ty: Type,
587587
588588 pub fn deinit(self: *Container, gpa: *Allocator) void {
......@@ -2464,6 +2464,48 @@ pub fn createAnonymousDecl(
24642464 return new_decl;
24652465}
24662466
2467pub fn createContainerDecl(
2468 self: *Module,
2469 scope: *Scope,
2470 base_token: std.zig.ast.TokenIndex,
2471 decl_arena: *std.heap.ArenaAllocator,
2472 typed_value: TypedValue,
2473) !*Decl {
2474 const scope_decl = scope.decl().?;
2475 const name = try self.getAnonTypeName(scope, base_token);
2476 defer self.gpa.free(name);
2477 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
2478 const src_hash: std.zig.SrcHash = undefined;
2479 const new_decl = try self.createNewDecl(scope, name, scope_decl.src_index, name_hash, src_hash);
2480 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
2481
2482 decl_arena_state.* = decl_arena.state;
2483 new_decl.typed_value = .{
2484 .most_recent = .{
2485 .typed_value = typed_value,
2486 .arena = decl_arena_state,
2487 },
2488 };
2489 new_decl.analysis = .complete;
2490 new_decl.generation = self.generation;
2491
2492 return new_decl;
2493}
2494
2495fn getAnonTypeName(self: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 {
2496 // TODO add namespaces, generic function signatrues
2497 const tree = scope.tree();
2498 const base_name = switch (tree.token_ids[base_token]) {
2499 .Keyword_struct => "struct",
2500 .Keyword_enum => "enum",
2501 .Keyword_union => "union",
2502 .Keyword_opaque => "opaque",
2503 else => unreachable,
2504 };
2505 const loc = tree.tokenLocationLoc(0, tree.token_locs[base_token]);
2506 return std.fmt.allocPrint(self.gpa, "{}:{}:{}", .{ base_name, loc.line, loc.column });
2507}
2508
24672509fn getNextAnonNameIndex(self: *Module) usize {
24682510 return @atomicRmw(usize, &self.next_anon_name_index, .Add, 1, .Monotonic);
24692511}
......@@ -2645,7 +2687,7 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst,
26452687}
26462688
26472689pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []const u8) !*Scope.File {
2648 const cur_pkg = scope.getOwnerPkg();
2690 const cur_pkg = scope.getFileScope().pkg;
26492691 const cur_pkg_dir_path = cur_pkg.root_src_directory.path orelse ".";
26502692 const found_pkg = cur_pkg.table.get(target_string);
26512693
src/astgen.zig+176-1
......@@ -282,6 +282,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
282282 .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?),
283283 .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?),
284284 .Switch => return switchExpr(mod, scope, rl, node.castTag(.Switch).?),
285 .ContainerDecl => return containerDecl(mod, scope, rl, node.castTag(.ContainerDecl).?),
285286
286287 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
287288 .Await => return mod.failNode(scope, node, "TODO implement astgen.expr for .Await", .{}),
......@@ -294,7 +295,6 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
294295 .Suspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Suspend", .{}),
295296 .AnyType => return mod.failNode(scope, node, "TODO implement astgen.expr for .AnyType", .{}),
296297 .FnProto => return mod.failNode(scope, node, "TODO implement astgen.expr for .FnProto", .{}),
297 .ContainerDecl => return mod.failNode(scope, node, "TODO implement astgen.expr for .ContainerDecl", .{}),
298298 .Nosuspend => return mod.failNode(scope, node, "TODO implement astgen.expr for .Nosuspend", .{}),
299299 }
300300}
......@@ -856,6 +856,181 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si
856856 return rlWrapPtr(mod, scope, rl, try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand));
857857}
858858
859fn containerField(
860 mod: *Module,
861 scope: *Scope,
862 node: *ast.Node.ContainerField,
863) InnerError!*zir.Inst {
864 const tree = scope.tree();
865 const src = tree.token_locs[node.firstToken()].start;
866 const name = try mod.identifierTokenString(scope, node.name_token);
867
868 if (node.comptime_token == null and node.value_expr == null and node.align_expr == null) {
869 if (node.type_expr) |some| {
870 const ty = try typeExpr(mod, scope, some);
871 return addZIRInst(mod, scope, src, zir.Inst.ContainerFieldTyped, .{
872 .bytes = name,
873 .ty = ty,
874 }, .{});
875 } else {
876 return addZIRInst(mod, scope, src, zir.Inst.ContainerFieldNamed, .{
877 .bytes = name,
878 }, .{});
879 }
880 }
881
882 const ty = if (node.type_expr) |some| try typeExpr(mod, scope, some) else null;
883 const alignment = if (node.align_expr) |some| try expr(mod, scope, .none, some) else null;
884 const init = if (node.value_expr) |some| try expr(mod, scope, .none, some) else null;
885
886 return addZIRInst(mod, scope, src, zir.Inst.ContainerField, .{
887 .bytes = name,
888 }, .{
889 .ty = ty,
890 .init = init,
891 .alignment = alignment,
892 .is_comptime = node.comptime_token != null,
893 });
894}
895
896fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ContainerDecl) InnerError!*zir.Inst {
897 const tree = scope.tree();
898 const src = tree.token_locs[node.kind_token].start;
899
900 var gen_scope: Scope.GenZIR = .{
901 .parent = scope,
902 .decl = scope.decl().?,
903 .arena = scope.arena(),
904 .instructions = .{},
905 };
906 defer gen_scope.instructions.deinit(mod.gpa);
907
908 var fields = std.ArrayList(*zir.Inst).init(mod.gpa);
909 defer fields.deinit();
910
911 for (node.fieldsAndDecls()) |fd| {
912 if (fd.castTag(.ContainerField)) |f| {
913 try fields.append(try containerField(mod, &gen_scope.base, f));
914 }
915 }
916
917 var decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
918 errdefer decl_arena.deinit();
919 const arena = &decl_arena.allocator;
920
921 var layout: std.builtin.TypeInfo.ContainerLayout = .Auto;
922 if (node.layout_token) |some| switch (tree.token_ids[some]) {
923 .Keyword_extern => layout = .Extern,
924 .Keyword_packed => layout = .Packed,
925 else => unreachable,
926 };
927
928 const container_type = switch (tree.token_ids[node.kind_token]) {
929 .Keyword_enum => blk: {
930 const tag_type: ?*zir.Inst = switch (node.init_arg_expr) {
931 .Type => |t| try typeExpr(mod, &gen_scope.base, t),
932 .None => null,
933 .Enum => unreachable,
934 };
935 const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.EnumType, .{
936 .fields = try arena.dupe(*zir.Inst, fields.items),
937 }, .{
938 .layout = layout,
939 .tag_type = tag_type,
940 });
941 const enum_type = try arena.create(Type.Payload.Enum);
942 enum_type.* = .{
943 .analysis = .{
944 .queued = .{
945 .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) },
946 .inst = inst,
947 },
948 },
949 .scope = .{
950 .file_scope = scope.getFileScope(),
951 .ty = Type.initPayload(&enum_type.base),
952 },
953 };
954 break :blk Type.initPayload(&enum_type.base);
955 },
956 .Keyword_struct => blk: {
957 assert(node.init_arg_expr == .None);
958 const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.StructType, .{
959 .fields = try arena.dupe(*zir.Inst, fields.items),
960 }, .{
961 .layout = layout,
962 });
963 const struct_type = try arena.create(Type.Payload.Struct);
964 struct_type.* = .{
965 .analysis = .{
966 .queued = .{
967 .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) },
968 .inst = inst,
969 },
970 },
971 .scope = .{
972 .file_scope = scope.getFileScope(),
973 .ty = Type.initPayload(&struct_type.base),
974 },
975 };
976 break :blk Type.initPayload(&struct_type.base);
977 },
978 .Keyword_union => blk: {
979 const init_inst = switch (node.init_arg_expr) {
980 .Enum => |e| if (e) |t| try typeExpr(mod, &gen_scope.base, t) else null,
981 .None => null,
982 .Type => |t| try typeExpr(mod, &gen_scope.base, t),
983 };
984 const init_kind: zir.Inst.UnionType.InitKind = switch (node.init_arg_expr) {
985 .Enum => .enum_type,
986 .None => .none,
987 .Type => .tag_type,
988 };
989 const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.UnionType, .{
990 .fields = try arena.dupe(*zir.Inst, fields.items),
991 }, .{
992 .layout = layout,
993 .init_kind = init_kind,
994 .init_inst = init_inst,
995 });
996 const union_type = try arena.create(Type.Payload.Union);
997 union_type.* = .{
998 .analysis = .{
999 .queued = .{
1000 .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) },
1001 .inst = inst,
1002 },
1003 },
1004 .scope = .{
1005 .file_scope = scope.getFileScope(),
1006 .ty = Type.initPayload(&union_type.base),
1007 },
1008 };
1009 break :blk Type.initPayload(&union_type.base);
1010 },
1011 .Keyword_opaque => blk: {
1012 if (fields.items.len > 0) {
1013 return mod.fail(scope, fields.items[0].src, "opaque types cannot have fields", .{});
1014 }
1015 const opaque_type = try arena.create(Type.Payload.Opaque);
1016 opaque_type.* = .{
1017 .scope = .{
1018 .file_scope = scope.getFileScope(),
1019 .ty = Type.initPayload(&opaque_type.base),
1020 },
1021 };
1022 break :blk Type.initPayload(&opaque_type.base);
1023 },
1024 else => unreachable,
1025 };
1026 const val = try Value.Tag.ty.create(arena, container_type);
1027 const decl = try mod.createContainerDecl(scope, node.kind_token, &decl_arena, .{
1028 .ty = Type.initTag(.type),
1029 .val = val,
1030 });
1031 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{}));
1032}
1033
8591034fn errorSetDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {
8601035 const tree = scope.tree();
8611036 const src = tree.token_locs[node.error_token].start;
src/type.zig+140-2
......@@ -49,7 +49,7 @@ pub const Type = extern union {
4949 .c_longdouble,
5050 => return .Float,
5151
52 .c_void => return .Opaque,
52 .c_void, .@"opaque" => return .Opaque,
5353 .bool => return .Bool,
5454 .void => return .Void,
5555 .type => return .Type,
......@@ -92,7 +92,9 @@ pub const Type = extern union {
9292
9393 .anyframe_T, .@"anyframe" => return .AnyFrame,
9494
95 .empty_struct => return .Struct,
95 .@"struct", .empty_struct => return .Struct,
96 .@"enum" => return .Enum,
97 .@"union" => return .Union,
9698 }
9799 }
98100
......@@ -470,6 +472,11 @@ pub const Type = extern union {
470472 .error_set => return self.copyPayloadShallow(allocator, Payload.Decl),
471473 .error_set_single => return self.copyPayloadShallow(allocator, Payload.Name),
472474 .empty_struct => return self.copyPayloadShallow(allocator, Payload.ContainerScope),
475
476 .@"enum" => return self.copyPayloadShallow(allocator, Payload.Enum),
477 .@"struct" => return self.copyPayloadShallow(allocator, Payload.Struct),
478 .@"union" => return self.copyPayloadShallow(allocator, Payload.Union),
479 .@"opaque" => return self.copyPayloadShallow(allocator, Payload.Opaque),
473480 }
474481 }
475482
......@@ -695,6 +702,11 @@ pub const Type = extern union {
695702 },
696703 .inferred_alloc_const => return out_stream.writeAll("(inferred_alloc_const)"),
697704 .inferred_alloc_mut => return out_stream.writeAll("(inferred_alloc_mut)"),
705 // TODO use declaration name
706 .@"enum" => return out_stream.writeAll("enum {}"),
707 .@"struct" => return out_stream.writeAll("struct {}"),
708 .@"union" => return out_stream.writeAll("union {}"),
709 .@"opaque" => return out_stream.writeAll("opaque {}"),
698710 }
699711 unreachable;
700712 }
......@@ -803,6 +815,10 @@ pub const Type = extern union {
803815 return payload.error_set.hasCodeGenBits() or payload.payload.hasCodeGenBits();
804816 },
805817
818 .@"enum" => @panic("TODO"),
819 .@"struct" => @panic("TODO"),
820 .@"union" => @panic("TODO"),
821
806822 .c_void,
807823 .void,
808824 .type,
......@@ -813,6 +829,7 @@ pub const Type = extern union {
813829 .@"undefined",
814830 .enum_literal,
815831 .empty_struct,
832 .@"opaque",
816833 => false,
817834
818835 .inferred_alloc_const => unreachable,
......@@ -924,6 +941,10 @@ pub const Type = extern union {
924941 @panic("TODO abiAlignment error union");
925942 },
926943
944 .@"enum" => self.cast(Payload.Enum).?.abiAlignment(target),
945 .@"struct" => @panic("TODO"),
946 .@"union" => @panic("TODO"),
947
927948 .c_void,
928949 .void,
929950 .type,
......@@ -936,6 +957,7 @@ pub const Type = extern union {
936957 .empty_struct,
937958 .inferred_alloc_const,
938959 .inferred_alloc_mut,
960 .@"opaque",
939961 => unreachable,
940962 };
941963 }
......@@ -961,6 +983,7 @@ pub const Type = extern union {
961983 .empty_struct => unreachable,
962984 .inferred_alloc_const => unreachable,
963985 .inferred_alloc_mut => unreachable,
986 .@"opaque" => unreachable,
964987
965988 .u8,
966989 .i8,
......@@ -1067,6 +1090,10 @@ pub const Type = extern union {
10671090 }
10681091 @panic("TODO abiSize error union");
10691092 },
1093
1094 .@"enum" => @panic("TODO"),
1095 .@"struct" => @panic("TODO"),
1096 .@"union" => @panic("TODO"),
10701097 };
10711098 }
10721099
......@@ -1134,6 +1161,10 @@ pub const Type = extern union {
11341161 .error_set,
11351162 .error_set_single,
11361163 .empty_struct,
1164 .@"enum",
1165 .@"struct",
1166 .@"union",
1167 .@"opaque",
11371168 => false,
11381169
11391170 .single_const_pointer,
......@@ -1205,6 +1236,10 @@ pub const Type = extern union {
12051236 .error_set,
12061237 .error_set_single,
12071238 .empty_struct,
1239 .@"enum",
1240 .@"struct",
1241 .@"union",
1242 .@"opaque",
12081243 => unreachable,
12091244
12101245 .const_slice,
......@@ -1297,6 +1332,10 @@ pub const Type = extern union {
12971332 .empty_struct,
12981333 .inferred_alloc_const,
12991334 .inferred_alloc_mut,
1335 .@"enum",
1336 .@"struct",
1337 .@"union",
1338 .@"opaque",
13001339 => false,
13011340
13021341 .const_slice,
......@@ -1371,6 +1410,10 @@ pub const Type = extern union {
13711410 .empty_struct,
13721411 .inferred_alloc_const,
13731412 .inferred_alloc_mut,
1413 .@"enum",
1414 .@"struct",
1415 .@"union",
1416 .@"opaque",
13741417 => false,
13751418
13761419 .single_const_pointer,
......@@ -1454,6 +1497,10 @@ pub const Type = extern union {
14541497 .empty_struct,
14551498 .inferred_alloc_const,
14561499 .inferred_alloc_mut,
1500 .@"enum",
1501 .@"struct",
1502 .@"union",
1503 .@"opaque",
14571504 => false,
14581505
14591506 .pointer => {
......@@ -1532,6 +1579,10 @@ pub const Type = extern union {
15321579 .empty_struct,
15331580 .inferred_alloc_const,
15341581 .inferred_alloc_mut,
1582 .@"enum",
1583 .@"struct",
1584 .@"union",
1585 .@"opaque",
15351586 => false,
15361587
15371588 .pointer => {
......@@ -1652,6 +1703,10 @@ pub const Type = extern union {
16521703 .empty_struct => unreachable,
16531704 .inferred_alloc_const => unreachable,
16541705 .inferred_alloc_mut => unreachable,
1706 .@"enum" => unreachable,
1707 .@"struct" => unreachable,
1708 .@"union" => unreachable,
1709 .@"opaque" => unreachable,
16551710
16561711 .array => self.castTag(.array).?.data.elem_type,
16571712 .array_sentinel => self.castTag(.array_sentinel).?.data.elem_type,
......@@ -1775,6 +1830,10 @@ pub const Type = extern union {
17751830 .empty_struct,
17761831 .inferred_alloc_const,
17771832 .inferred_alloc_mut,
1833 .@"enum",
1834 .@"struct",
1835 .@"union",
1836 .@"opaque",
17781837 => unreachable,
17791838
17801839 .array => self.castTag(.array).?.data.len,
......@@ -1843,6 +1902,10 @@ pub const Type = extern union {
18431902 .empty_struct,
18441903 .inferred_alloc_const,
18451904 .inferred_alloc_mut,
1905 .@"enum",
1906 .@"struct",
1907 .@"union",
1908 .@"opaque",
18461909 => unreachable,
18471910
18481911 .single_const_pointer,
......@@ -1928,6 +1991,10 @@ pub const Type = extern union {
19281991 .empty_struct,
19291992 .inferred_alloc_const,
19301993 .inferred_alloc_mut,
1994 .@"enum",
1995 .@"struct",
1996 .@"union",
1997 .@"opaque",
19311998 => false,
19321999
19332000 .int_signed,
......@@ -2005,6 +2072,10 @@ pub const Type = extern union {
20052072 .empty_struct,
20062073 .inferred_alloc_const,
20072074 .inferred_alloc_mut,
2075 .@"enum",
2076 .@"struct",
2077 .@"union",
2078 .@"opaque",
20082079 => false,
20092080
20102081 .int_unsigned,
......@@ -2072,6 +2143,10 @@ pub const Type = extern union {
20722143 .empty_struct,
20732144 .inferred_alloc_const,
20742145 .inferred_alloc_mut,
2146 .@"enum",
2147 .@"struct",
2148 .@"union",
2149 .@"opaque",
20752150 => unreachable,
20762151
20772152 .int_unsigned => .{
......@@ -2163,6 +2238,10 @@ pub const Type = extern union {
21632238 .empty_struct,
21642239 .inferred_alloc_const,
21652240 .inferred_alloc_mut,
2241 .@"enum",
2242 .@"struct",
2243 .@"union",
2244 .@"opaque",
21662245 => false,
21672246
21682247 .usize,
......@@ -2277,6 +2356,10 @@ pub const Type = extern union {
22772356 .empty_struct,
22782357 .inferred_alloc_const,
22792358 .inferred_alloc_mut,
2359 .@"enum",
2360 .@"struct",
2361 .@"union",
2362 .@"opaque",
22802363 => unreachable,
22812364 };
22822365 }
......@@ -2357,6 +2440,10 @@ pub const Type = extern union {
23572440 .empty_struct,
23582441 .inferred_alloc_const,
23592442 .inferred_alloc_mut,
2443 .@"enum",
2444 .@"struct",
2445 .@"union",
2446 .@"opaque",
23602447 => unreachable,
23612448 }
23622449 }
......@@ -2436,6 +2523,10 @@ pub const Type = extern union {
24362523 .empty_struct,
24372524 .inferred_alloc_const,
24382525 .inferred_alloc_mut,
2526 .@"enum",
2527 .@"struct",
2528 .@"union",
2529 .@"opaque",
24392530 => unreachable,
24402531 }
24412532 }
......@@ -2515,6 +2606,10 @@ pub const Type = extern union {
25152606 .empty_struct,
25162607 .inferred_alloc_const,
25172608 .inferred_alloc_mut,
2609 .@"enum",
2610 .@"struct",
2611 .@"union",
2612 .@"opaque",
25182613 => unreachable,
25192614 };
25202615 }
......@@ -2591,6 +2686,10 @@ pub const Type = extern union {
25912686 .empty_struct,
25922687 .inferred_alloc_const,
25932688 .inferred_alloc_mut,
2689 .@"enum",
2690 .@"struct",
2691 .@"union",
2692 .@"opaque",
25942693 => unreachable,
25952694 };
25962695 }
......@@ -2667,6 +2766,10 @@ pub const Type = extern union {
26672766 .empty_struct,
26682767 .inferred_alloc_const,
26692768 .inferred_alloc_mut,
2769 .@"enum",
2770 .@"struct",
2771 .@"union",
2772 .@"opaque",
26702773 => unreachable,
26712774 };
26722775 }
......@@ -2743,6 +2846,10 @@ pub const Type = extern union {
27432846 .empty_struct,
27442847 .inferred_alloc_const,
27452848 .inferred_alloc_mut,
2849 .@"enum",
2850 .@"struct",
2851 .@"union",
2852 .@"opaque",
27462853 => false,
27472854 };
27482855 }
......@@ -2800,8 +2907,13 @@ pub const Type = extern union {
28002907 .error_union,
28012908 .error_set,
28022909 .error_set_single,
2910 .@"opaque",
28032911 => return null,
28042912
2913 .@"enum" => @panic("TODO onePossibleValue enum"),
2914 .@"struct" => @panic("TODO onePossibleValue struct"),
2915 .@"union" => @panic("TODO onePossibleValue union"),
2916
28052917 .empty_struct => return Value.initTag(.empty_struct_value),
28062918 .void => return Value.initTag(.void_value),
28072919 .noreturn => return Value.initTag(.unreachable_value),
......@@ -2907,6 +3019,10 @@ pub const Type = extern union {
29073019 .empty_struct,
29083020 .inferred_alloc_const,
29093021 .inferred_alloc_mut,
3022 .@"enum",
3023 .@"struct",
3024 .@"union",
3025 .@"opaque",
29103026 => return false,
29113027
29123028 .c_const_pointer,
......@@ -2997,6 +3113,10 @@ pub const Type = extern union {
29973113 => unreachable,
29983114
29993115 .empty_struct => self.castTag(.empty_struct).?.data,
3116 .@"enum" => &self.castTag(.@"enum").?.scope,
3117 .@"struct" => &self.castTag(.@"struct").?.scope,
3118 .@"union" => &self.castTag(.@"union").?.scope,
3119 .@"opaque" => &self.castTag(.@"opaque").?.scope,
30003120 };
30013121 }
30023122
......@@ -3137,6 +3257,10 @@ pub const Type = extern union {
31373257 error_set,
31383258 error_set_single,
31393259 empty_struct,
3260 @"enum",
3261 @"struct",
3262 @"union",
3263 @"opaque",
31403264
31413265 pub const last_no_payload_tag = Tag.inferred_alloc_const;
31423266 pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
......@@ -3219,6 +3343,10 @@ pub const Type = extern union {
32193343 .error_set => Payload.Decl,
32203344 .error_set_single => Payload.Name,
32213345 .empty_struct => Payload.ContainerScope,
3346 .@"enum" => Payload.Enum,
3347 .@"struct" => Payload.Struct,
3348 .@"union" => Payload.Union,
3349 .@"opaque" => Payload.Opaque,
32223350 };
32233351 }
32243352
......@@ -3332,6 +3460,16 @@ pub const Type = extern union {
33323460 base: Payload,
33333461 data: *Module.Scope.Container,
33343462 };
3463
3464 pub const Opaque = struct {
3465 base: Payload = .{ .tag = .@"opaque" },
3466
3467 scope: Module.Scope.Container,
3468 };
3469
3470 pub const Enum = @import("type/Enum.zig");
3471 pub const Struct = @import("type/Struct.zig");
3472 pub const Union = @import("type/Union.zig");
33353473 };
33363474};
33373475
src/type/Enum.zig created+55
......@@ -0,0 +1,55 @@
1const std = @import("std");
2const zir = @import("../zir.zig");
3const Value = @import("../value.zig").Value;
4const Type = @import("../type.zig").Type;
5const Module = @import("../Module.zig");
6const Scope = Module.Scope;
7const Enum = @This();
8
9base: Type.Payload = .{ .tag = .@"enum" },
10
11analysis: union(enum) {
12 queued: Zir,
13 in_progress,
14 resolved: Size,
15 failed,
16},
17scope: Scope.Container,
18
19pub const Field = struct {
20 value: Value,
21};
22
23pub const Zir = struct {
24 body: zir.Module.Body,
25 inst: *zir.Inst,
26};
27
28pub const Size = struct {
29 tag_type: Type,
30 fields: std.StringArrayHashMapUnmanaged(Field),
31};
32
33pub fn resolve(self: *Enum, mod: *Module, scope: *Scope) !void {
34 const zir = switch (self.analysis) {
35 .failed => return error.AnalysisFail,
36 .resolved => return,
37 .in_progress => {
38 return mod.fail(scope, src, "enum '{}' depends on itself", .{enum_name});
39 },
40 .queued => |zir| zir,
41 };
42 self.analysis = .in_progress;
43
44 // TODO
45}
46
47// TODO should this resolve the type or assert that it has already been resolved?
48pub fn abiAlignment(self: *Enum, target: std.Target) u32 {
49 switch (self.analysis) {
50 .queued => unreachable, // alignment has not been resolved
51 .in_progress => unreachable, // alignment has not been resolved
52 .failed => unreachable, // type resolution failed
53 .resolved => |r| return r.tag_type.abiAlignment(target),
54 }
55}
src/type/Struct.zig created+56
......@@ -0,0 +1,56 @@
1const std = @import("std");
2const zir = @import("../zir.zig");
3const Value = @import("../value.zig").Value;
4const Type = @import("../type.zig").Type;
5const Module = @import("../Module.zig");
6const Scope = Module.Scope;
7const Struct = @This();
8
9base: Type.Payload = .{ .tag = .@"struct" },
10
11analysis: union(enum) {
12 queued: Zir,
13 zero_bits_in_progress,
14 zero_bits: Zero,
15 in_progress,
16 // alignment: Align,
17 resolved: Size,
18 failed,
19},
20scope: Scope.Container,
21
22pub const Field = struct {
23 value: Value,
24};
25
26pub const Zir = struct {
27 body: zir.Module.Body,
28 inst: *zir.Inst,
29};
30
31pub const Zero = struct {
32 is_zero_bits: bool,
33 fields: std.StringArrayHashMapUnmanaged(Field),
34};
35
36pub const Size = struct {
37 is_zero_bits: bool,
38 alignment: u32,
39 size: u32,
40 fields: std.StringArrayHashMapUnmanaged(Field),
41};
42
43pub fn resolveZeroBits(self: *Struct, mod: *Module, scope: *Scope) !void {
44 const zir = switch (self.analysis) {
45 .failed => return error.AnalysisFail,
46 .zero_bits_in_progress => {
47 return mod.fail(scope, src, "struct '{}' depends on itself", .{});
48 },
49 .queued => |zir| zir,
50 else => return,
51 };
52
53 self.analysis = .zero_bits_in_progress;
54
55 // TODO
56}
src/type/Union.zig created+56
......@@ -0,0 +1,56 @@
1const std = @import("std");
2const zir = @import("../zir.zig");
3const Value = @import("../value.zig").Value;
4const Type = @import("../type.zig").Type;
5const Module = @import("../Module.zig");
6const Scope = Module.Scope;
7const Union = @This();
8
9base: Type.Payload = .{ .tag = .@"struct" },
10
11analysis: union(enum) {
12 queued: Zir,
13 zero_bits_in_progress,
14 zero_bits: Zero,
15 in_progress,
16 // alignment: Align,
17 resolved: Size,
18 failed,
19},
20scope: Scope.Container,
21
22pub const Field = struct {
23 value: Value,
24};
25
26pub const Zir = struct {
27 body: zir.Module.Body,
28 inst: *zir.Inst,
29};
30
31pub const Zero = struct {
32 is_zero_bits: bool,
33 fields: std.StringArrayHashMapUnmanaged(Field),
34};
35
36pub const Size = struct {
37 is_zero_bits: bool,
38 alignment: u32,
39 size: u32,
40 fields: std.StringArrayHashMapUnmanaged(Field),
41};
42
43pub fn resolveZeroBits(self: *Union, mod: *Module, scope: *Scope) !void {
44 const zir = switch (self.analysis) {
45 .failed => return error.AnalysisFail,
46 .zero_bits_in_progress => {
47 return mod.fail(scope, src, "union '{}' depends on itself", .{});
48 },
49 .queued => |zir| zir,
50 else => return,
51 };
52
53 self.analysis = .zero_bits_in_progress;
54
55 // TODO
56}
src/value.zig+1-1
......@@ -389,7 +389,6 @@ pub const Value = extern union {
389389 },
390390 .@"error" => return self.copyPayloadShallow(allocator, Payload.Error),
391391
392 // memory is managed by the declaration
393392 .error_set => return self.copyPayloadShallow(allocator, Payload.ErrorSet),
394393
395394 .inferred_alloc => unreachable,
......@@ -2025,6 +2024,7 @@ pub const Value = extern union {
20252024 data: f128,
20262025 };
20272026
2027 // TODO move to type.zig
20282028 pub const ErrorSet = struct {
20292029 pub const base_tag = Tag.error_set;
20302030
src/zir.zig+107-1
......@@ -133,6 +133,12 @@ pub const Inst = struct {
133133 condbr,
134134 /// Special case, has no textual representation.
135135 @"const",
136 /// Container field with just the name.
137 container_field_named,
138 /// Container field with a type and a name,
139 container_field_typed,
140 /// Container field with all the bells and whistles.
141 container_field,
136142 /// Declares the beginning of a statement. Used for debug info.
137143 dbg_stmt,
138144 /// Represents a pointer to a global decl by name.
......@@ -263,6 +269,8 @@ pub const Inst = struct {
263269 store_to_inferred_ptr,
264270 /// String Literal. Makes an anonymous Decl and then takes a pointer to it.
265271 str,
272 /// Create a struct type.
273 struct_type,
266274 /// Arithmetic subtraction. Asserts no integer overflow.
267275 sub,
268276 /// Twos complement wrapping integer subtraction.
......@@ -282,6 +290,8 @@ pub const Inst = struct {
282290 xor,
283291 /// Create an optional type '?T'
284292 optional_type,
293 /// Create a union type.
294 union_type,
285295 /// Unwraps an optional value 'lhs.?'
286296 unwrap_optional_safe,
287297 /// Same as previous, but without safety checks. Used for orelse, if and while
......@@ -294,8 +304,10 @@ pub const Inst = struct {
294304 unwrap_err_code,
295305 /// Takes a *E!T and raises a compiler error if T != void
296306 ensure_err_payload_void,
297 /// Enum literal
307 /// Create a enum literal,
298308 enum_literal,
309 /// Create an enum type.
310 enum_type,
299311 /// A switch expression.
300312 switchbr,
301313 /// A range in a switch case, `lhs...rhs`.
......@@ -430,6 +442,12 @@ pub const Inst = struct {
430442 .slice => Slice,
431443 .switchbr => SwitchBr,
432444 .typeof_peer => TypeOfPeer,
445 .container_field_named => ContainerFieldNamed,
446 .container_field_typed => ContainerFieldTyped,
447 .container_field => ContainerField,
448 .enum_type => EnumType,
449 .union_type => UnionType,
450 .struct_type => StructType,
433451 };
434452 }
435453
......@@ -544,6 +562,9 @@ pub const Inst = struct {
544562 .resolve_inferred_alloc,
545563 .set_eval_branch_quota,
546564 .compilelog,
565 .enum_type,
566 .union_type,
567 .struct_type,
547568 => false,
548569
549570 .@"break",
......@@ -556,6 +577,9 @@ pub const Inst = struct {
556577 .@"unreachable",
557578 .loop,
558579 .switchbr,
580 .container_field_named,
581 .container_field_typed,
582 .container_field,
559583 => true,
560584 };
561585 }
......@@ -1079,6 +1103,88 @@ pub const Inst = struct {
10791103 },
10801104 kw_args: struct {},
10811105 };
1106
1107 pub const ContainerFieldNamed = struct {
1108 pub const base_tag = Tag.container_field_named;
1109 base: Inst,
1110
1111 positionals: struct {
1112 bytes: []const u8,
1113 },
1114 kw_args: struct {},
1115 };
1116
1117 pub const ContainerFieldTyped = struct {
1118 pub const base_tag = Tag.container_field_typed;
1119 base: Inst,
1120
1121 positionals: struct {
1122 bytes: []const u8,
1123 ty: *Inst,
1124 },
1125 kw_args: struct {},
1126 };
1127
1128 pub const ContainerField = struct {
1129 pub const base_tag = Tag.container_field;
1130 base: Inst,
1131
1132 positionals: struct {
1133 bytes: []const u8,
1134 },
1135 kw_args: struct {
1136 ty: ?*Inst = null,
1137 init: ?*Inst = null,
1138 alignment: ?*Inst = null,
1139 is_comptime: bool = false,
1140 },
1141 };
1142
1143 pub const EnumType = struct {
1144 pub const base_tag = Tag.enum_type;
1145 base: Inst,
1146
1147 positionals: struct {
1148 fields: []*Inst,
1149 },
1150 kw_args: struct {
1151 tag_type: ?*Inst = null,
1152 layout: std.builtin.TypeInfo.ContainerLayout = .Auto,
1153 },
1154 };
1155
1156 pub const StructType = struct {
1157 pub const base_tag = Tag.struct_type;
1158 base: Inst,
1159
1160 positionals: struct {
1161 fields: []*Inst,
1162 },
1163 kw_args: struct {
1164 layout: std.builtin.TypeInfo.ContainerLayout = .Auto,
1165 },
1166 };
1167
1168 pub const UnionType = struct {
1169 pub const base_tag = Tag.union_type;
1170 base: Inst,
1171
1172 positionals: struct {
1173 fields: []*Inst,
1174 },
1175 kw_args: struct {
1176 init_inst: ?*Inst = null,
1177 init_kind: InitKind = .none,
1178 layout: std.builtin.TypeInfo.ContainerLayout = .Auto,
1179 },
1180
1181 // TODO error: values of type '(enum literal)' must be comptime known
1182 pub const InitKind = enum {
1183 enum_type,
1184 tag_type,
1185 none,
1186 };
1187 };
10821188};
10831189
10841190pub const ErrorMsg = struct {
src/zir_sema.zig+8
......@@ -155,6 +155,14 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
155155 .switch_range => return analyzeInstSwitchRange(mod, scope, old_inst.castTag(.switch_range).?),
156156 .booland => return analyzeInstBoolOp(mod, scope, old_inst.castTag(.booland).?),
157157 .boolor => return analyzeInstBoolOp(mod, scope, old_inst.castTag(.boolor).?),
158
159 .container_field_named,
160 .container_field_typed,
161 .container_field,
162 .enum_type,
163 .union_type,
164 .struct_type,
165 => return mod.fail(scope, old_inst.src, "TODO analyze container instructions", .{}),
158166 }
159167}
160168