authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-10 22:50:00-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-10 22:50:00-07:00
logdae22a0a1f13cc963e96cd704941eed29b8dde27
treed353e68f224f4c8d9447ea2560ab1cd79189fbf5
parentb9a099e83cf11629554c68c7606836065133f56b

stage2: struct, union, enum, opaque, error sets get better names

This commit takes advantage of the new "NameStrategy" that is exposed in the ZIR in order to name Decls after their parent when asked to. This makes the next failing test case pass.

3 files changed, 67 insertions(+), 18 deletions(-)

BRANCH_TODO+10-2
...@@ -1,5 +1,13 @@...@@ -1,5 +1,13 @@
1 * structs, unions, enums, etc get weird names such as "Point__anon_22" rather1 * The next problem is that when trying to deinitialize everything, when we
2 than "Point".2 deinit a Decl that is the owner of a Namespace, there may still be other Decl
3 objects that reference that Namespace. They want to check if they are the owner
4 in order to find out if they should destroy it. But they can't check if they are
5 the owner because the owner_decl field is destroyed.
6 So there's a memory management problem to solve. We could easily solve this with
7 ref counting or whatever but the goal is to not introduce extra overhead / unnecessary
8 fields just to help figure out how to free stuff. So come up with some way to make
9 this sound, and easily debuggable when something goes wrong.
10
3 * get stage2 tests passing11 * get stage2 tests passing
4 * modify stage2 tests so that only 1 uses _start and the rest use12 * modify stage2 tests so that only 1 uses _start and the rest use
5 pub fn main13 pub fn main
src/Module.zig+19-8
...@@ -3759,17 +3759,19 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b...@@ -3759,17 +3759,19 @@ pub fn constIntBig(mod: *Module, arena: *Allocator, src: LazySrcLoc, ty: Type, b
3759 }3759 }
3760}3760}
37613761
3762pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {3762/// Takes ownership of `name` even if it returns an error.
3763pub fn createAnonymousDeclNamed(
3764 mod: *Module,
3765 scope: *Scope,
3766 typed_value: TypedValue,
3767 name: [:0]u8,
3768) !*Decl {
3769 errdefer mod.gpa.free(name);
3770
3763 const scope_decl = scope.ownerDecl().?;3771 const scope_decl = scope.ownerDecl().?;
3764 const namespace = scope_decl.namespace;3772 const namespace = scope_decl.namespace;
3765 try namespace.anon_decls.ensureUnusedCapacity(mod.gpa, 1);3773 try namespace.anon_decls.ensureUnusedCapacity(mod.gpa, 1);
37663774
3767 const name_index = mod.getNextAnonNameIndex();
3768 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
3769 scope_decl.name, name_index,
3770 });
3771 errdefer mod.gpa.free(name);
3772
3773 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);3775 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
37743776
3775 new_decl.name = name;3777 new_decl.name = name;
...@@ -3793,7 +3795,16 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)...@@ -3793,7 +3795,16 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)
3793 return new_decl;3795 return new_decl;
3794}3796}
37953797
3796fn getNextAnonNameIndex(mod: *Module) usize {3798pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue) !*Decl {
3799 const scope_decl = scope.ownerDecl().?;
3800 const name_index = mod.getNextAnonNameIndex();
3801 const name = try std.fmt.allocPrintZ(mod.gpa, "{s}__anon_{d}", .{
3802 scope_decl.name, name_index,
3803 });
3804 return mod.createAnonymousDeclNamed(scope, typed_value, name);
3805}
3806
3807pub fn getNextAnonNameIndex(mod: *Module) usize {
3797 return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic);3808 return @atomicRmw(usize, &mod.next_anon_name_index, .Add, 1, .Monotonic);
3798}3809}
37993810
src/Sema.zig+38-8
...@@ -719,10 +719,11 @@ fn zirStructDecl(...@@ -719,10 +719,11 @@ fn zirStructDecl(
719 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);719 const struct_obj = try new_decl_arena.allocator.create(Module.Struct);
720 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);720 const struct_ty = try Type.Tag.@"struct".create(&new_decl_arena.allocator, struct_obj);
721 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);721 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);
722 const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{722 const type_name = try sema.createTypeName(block, small.name_strategy);
723 const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{
723 .ty = Type.initTag(.type),724 .ty = Type.initTag(.type),
724 .val = struct_val,725 .val = struct_val,
725 });726 }, type_name);
726 struct_obj.* = .{727 struct_obj.* = .{
727 .owner_decl = new_decl,728 .owner_decl = new_decl,
728 .fields = .{},729 .fields = .{},
...@@ -744,6 +745,32 @@ fn zirStructDecl(...@@ -744,6 +745,32 @@ fn zirStructDecl(
744 return sema.analyzeDeclVal(block, src, new_decl);745 return sema.analyzeDeclVal(block, src, new_decl);
745}746}
746747
748fn createTypeName(sema: *Sema, block: *Scope.Block, name_strategy: Zir.Inst.NameStrategy) ![:0]u8 {
749 switch (name_strategy) {
750 .anon => {
751 // It would be neat to have "struct:line:column" but this name has
752 // to survive incremental updates, where it may have been shifted down
753 // or up to a different line, but unchanged, and thus not unnecessarily
754 // semantically analyzed.
755 const name_index = sema.mod.getNextAnonNameIndex();
756 return std.fmt.allocPrintZ(sema.gpa, "{s}__anon_{d}", .{
757 sema.owner_decl.name, name_index,
758 });
759 },
760 .parent => return sema.gpa.dupeZ(u8, mem.spanZ(sema.owner_decl.name)),
761 .func => {
762 const name_index = sema.mod.getNextAnonNameIndex();
763 const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__anon_{d}", .{
764 sema.owner_decl.name, name_index,
765 });
766 log.warn("TODO: handle NameStrategy.func correctly instead of using anon name '{s}'", .{
767 name,
768 });
769 return name;
770 },
771 }
772}
773
747fn zirEnumDecl(774fn zirEnumDecl(
748 sema: *Sema,775 sema: *Sema,
749 block: *Scope.Block,776 block: *Scope.Block,
...@@ -807,10 +834,11 @@ fn zirEnumDecl(...@@ -807,10 +834,11 @@ fn zirEnumDecl(
807 };834 };
808 const enum_ty = Type.initPayload(&enum_ty_payload.base);835 const enum_ty = Type.initPayload(&enum_ty_payload.base);
809 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);836 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);
810 const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{837 const type_name = try sema.createTypeName(block, small.name_strategy);
838 const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{
811 .ty = Type.initTag(.type),839 .ty = Type.initTag(.type),
812 .val = enum_val,840 .val = enum_val,
813 });841 }, type_name);
814 enum_obj.* = .{842 enum_obj.* = .{
815 .owner_decl = new_decl,843 .owner_decl = new_decl,
816 .tag_ty = tag_ty,844 .tag_ty = tag_ty,
...@@ -957,10 +985,11 @@ fn zirUnionDecl(...@@ -957,10 +985,11 @@ fn zirUnionDecl(
957 const union_obj = try new_decl_arena.allocator.create(Module.Union);985 const union_obj = try new_decl_arena.allocator.create(Module.Union);
958 const union_ty = try Type.Tag.@"union".create(&new_decl_arena.allocator, union_obj);986 const union_ty = try Type.Tag.@"union".create(&new_decl_arena.allocator, union_obj);
959 const union_val = try Value.Tag.ty.create(&new_decl_arena.allocator, union_ty);987 const union_val = try Value.Tag.ty.create(&new_decl_arena.allocator, union_ty);
960 const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{988 const type_name = try sema.createTypeName(block, small.name_strategy);
989 const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{
961 .ty = Type.initTag(.type),990 .ty = Type.initTag(.type),
962 .val = union_val,991 .val = union_val,
963 });992 }, type_name);
964 union_obj.* = .{993 union_obj.* = .{
965 .owner_decl = new_decl,994 .owner_decl = new_decl,
966 .tag_ty = Type.initTag(.@"null"),995 .tag_ty = Type.initTag(.@"null"),
...@@ -1021,10 +1050,11 @@ fn zirErrorSetDecl(...@@ -1021,10 +1050,11 @@ fn zirErrorSetDecl(
1021 const error_set = try new_decl_arena.allocator.create(Module.ErrorSet);1050 const error_set = try new_decl_arena.allocator.create(Module.ErrorSet);
1022 const error_set_ty = try Type.Tag.error_set.create(&new_decl_arena.allocator, error_set);1051 const error_set_ty = try Type.Tag.error_set.create(&new_decl_arena.allocator, error_set);
1023 const error_set_val = try Value.Tag.ty.create(&new_decl_arena.allocator, error_set_ty);1052 const error_set_val = try Value.Tag.ty.create(&new_decl_arena.allocator, error_set_ty);
1024 const new_decl = try sema.mod.createAnonymousDecl(&block.base, .{1053 const type_name = try sema.createTypeName(block, name_strategy);
1054 const new_decl = try sema.mod.createAnonymousDeclNamed(&block.base, .{
1025 .ty = Type.initTag(.type),1055 .ty = Type.initTag(.type),
1026 .val = error_set_val,1056 .val = error_set_val,
1027 });1057 }, type_name);
1028 const names = try new_decl_arena.allocator.alloc([]const u8, fields.len);1058 const names = try new_decl_arena.allocator.alloc([]const u8, fields.len);
1029 for (fields) |str_index, i| {1059 for (fields) |str_index, i| {
1030 names[i] = try new_decl_arena.allocator.dupe(u8, sema.code.nullTerminatedString(str_index));1060 names[i] = try new_decl_arena.allocator.dupe(u8, sema.code.nullTerminatedString(str_index));