authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-11-16 20:45:53+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-11-17 21:19:49+02:00
logc1e19f4c0a62047c26d5baabe25887e533cc739f
tree921e818474ece6846d958fabf1a99c0ab3cc3df8
parentf173d078c780c9946742c4ce686ccd0dccdb7e98
signaturelock-open Commit is signed but in an unrecognized format.

stage2: initial container astgen


8 files changed, 228 insertions(+), 41 deletions(-)

src/Module.zig+23-9
......@@ -469,12 +469,12 @@ pub const Scope = struct {
469469 }
470470 }
471471
472 pub fn getOwnerPkg(base: *Scope) *Package {
472 pub fn getFileScope(base: *Scope) *Scope.File {
473473 var cur = base;
474474 while (true) {
475475 cur = switch (cur.tag) {
476 .container => return @fieldParentPtr(Container, "base", cur).file_scope.pkg,
477 .file => return @fieldParentPtr(File, "base", cur).pkg,
476 .container => return @fieldParentPtr(Container, "base", cur).file_scope,
477 .file => return @fieldParentPtr(File, "base", cur),
478478 .zir_module => unreachable, // TODO are zir modules allowed to import packages?
479479 .gen_zir => @fieldParentPtr(GenZIR, "base", cur).parent,
480480 .local_val => @fieldParentPtr(LocalVal, "base", cur).parent,
......@@ -550,7 +550,7 @@ pub const Scope = struct {
550550 file_scope: *Scope.File,
551551
552552 /// Direct children of the file.
553 decls: std.AutoArrayHashMapUnmanaged(*Decl, void),
553 decls: std.AutoArrayHashMapUnmanaged(*Decl, void) = .{},
554554 ty: Type,
555555
556556 pub fn deinit(self: *Container, gpa: *Allocator) void {
......@@ -2273,8 +2273,15 @@ pub fn createAnonymousDecl(
22732273 return new_decl;
22742274}
22752275
2276fn createContainerDecl(self: *Module, scope: *Scope, container_node: *std.zig.ast.Node.ContainerDecl) !*Decl {
2277 const name = try self.getAnonTypeName(scope, container_node.kind_token);
2276pub fn createContainerDecl(
2277 self: *Module,
2278 scope: *Scope,
2279 base_token: std.zig.ast.TokenIndex,
2280 decl_arena: *std.heap.ArenaAllocator,
2281 typed_value: TypedValue,
2282) !*Decl {
2283 const scope_decl = scope.decl().?;
2284 const name = try self.getAnonTypeName(scope, base_token);
22782285 defer self.gpa.free(name);
22792286 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
22802287 const src_hash: std.zig.SrcHash = undefined;
......@@ -2282,18 +2289,25 @@ fn createContainerDecl(self: *Module, scope: *Scope, container_node: *std.zig.as
22822289 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
22832290
22842291 decl_arena_state.* = decl_arena.state;
2292 new_decl.typed_value = .{
2293 .most_recent = .{
2294 .typed_value = typed_value,
2295 .arena = decl_arena_state,
2296 },
2297 };
2298 new_decl.analysis = .complete;
22852299 new_decl.generation = self.generation;
22862300
22872301 return new_decl;
22882302}
22892303
22902304fn getAnonTypeName(self: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 {
2291 const container = scope.getContainer();
2292 const tree = self.getAstTree(container);
2305 const tree = scope.tree();
22932306 const base_name = switch (tree.token_ids[base_token]) {
22942307 .Keyword_struct => "struct",
22952308 .Keyword_enum => "enum",
22962309 .Keyword_union => "union",
2310 .Keyword_opaque => "opaque",
22972311 else => unreachable,
22982312 };
22992313 const loc = tree.tokenLocationLoc(0, tree.token_locs[base_token]);
......@@ -2487,7 +2501,7 @@ pub fn analyzeSlice(self: *Module, scope: *Scope, src: usize, array_ptr: *Inst,
24872501}
24882502
24892503pub fn analyzeImport(self: *Module, scope: *Scope, src: usize, target_string: []const u8) !*Scope.File {
2490 const cur_pkg = scope.getOwnerPkg();
2504 const cur_pkg = scope.getFileScope().pkg;
24912505 const cur_pkg_dir_path = cur_pkg.root_src_directory.path orelse ".";
24922506 const found_pkg = cur_pkg.table.get(target_string);
24932507
src/astgen.zig+163-1
......@@ -281,6 +281,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
281281 .Comptime => return comptimeKeyword(mod, scope, rl, node.castTag(.Comptime).?),
282282 .OrElse => return orelseExpr(mod, scope, rl, node.castTag(.OrElse).?),
283283 .Switch => return switchExpr(mod, scope, rl, node.castTag(.Switch).?),
284 .ContainerDecl => return containerDecl(mod, scope, rl, node.castTag(.ContainerDecl).?),
284285
285286 .Defer => return mod.failNode(scope, node, "TODO implement astgen.expr for .Defer", .{}),
286287 .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 .Continue => return mod.failNode(scope, node, "TODO implement astgen.expr for .Continue", .{}),
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}
......@@ -765,6 +765,168 @@ fn unwrapOptional(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.Si
765765 return rlWrapPtr(mod, scope, rl, try addZIRUnOp(mod, scope, src, .unwrap_optional_safe, operand));
766766}
767767
768fn containerField(mod: *Module, scope: *Scope, node: *ast.Node.ContainerField) InnerError!*zir.Inst {
769 const tree = scope.tree();
770 const src = tree.token_locs[node.firstToken()].start;
771 const name = try identifierTokenString(mod, scope, node.name_token);
772
773 if (node.comptime_token == null and node.value_expr == null and node.align_expr == null) {
774 if (node.type_expr) |some| {
775 const ty = try typeExpr(mod, scope, some);
776 return addZIRInst(mod, scope, src, zir.Inst.ContainerFieldTyped, .{
777 .bytes = name,
778 .ty = ty,
779 }, .{});
780 } else {
781 return addZIRInst(mod, scope, src, zir.Inst.ContainerFieldNamed, .{
782 .bytes = name,
783 }, .{});
784 }
785 }
786
787 const ty = if (node.type_expr) |some| try typeExpr(mod, scope, some) else null;
788 const alignment = if (node.align_expr) |some| try expr(mod, scope, .none, some) else null;
789 const init = if (node.value_expr) |some| try expr(mod, scope, .none, some) else null;
790
791 return addZIRInst(mod, scope, src, zir.Inst.ContainerField, .{
792 .bytes = name,
793 }, .{
794 .ty = ty,
795 .init = init,
796 .alignment = alignment,
797 .is_comptime = node.comptime_token != null,
798 });
799}
800
801fn containerDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ContainerDecl) InnerError!*zir.Inst {
802 const tree = scope.tree();
803 const src = tree.token_locs[node.kind_token].start;
804
805 var gen_scope: Scope.GenZIR = .{
806 .parent = scope,
807 .decl = scope.decl().?,
808 .arena = scope.arena(),
809 .instructions = .{},
810 };
811 defer gen_scope.instructions.deinit(mod.gpa);
812
813 var fields = std.ArrayList(*zir.Inst).init(mod.gpa);
814 defer fields.deinit();
815
816 for (node.fieldsAndDecls()) |fd| {
817 if (fd.castTag(.ContainerField)) |f| {
818 try fields.append(try containerField(mod, &gen_scope.base, f));
819 }
820 }
821
822 var decl_arena = std.heap.ArenaAllocator.init(mod.gpa);
823 errdefer decl_arena.deinit();
824 const arena = &decl_arena.allocator;
825
826 var layout: std.builtin.TypeInfo.ContainerLayout = .Auto;
827 if (node.layout_token) |some| switch (tree.token_ids[some]) {
828 .Keyword_extern => layout = .Extern,
829 .Keyword_packed => layout = .Packed,
830 else => unreachable,
831 };
832
833 const container_type = switch (tree.token_ids[node.kind_token]) {
834 .Keyword_enum => blk: {
835 const tag_type: ?*zir.Inst = switch (node.init_arg_expr) {
836 .Type => |t| try typeExpr(mod, &gen_scope.base, t),
837 .None => null,
838 .Enum => unreachable,
839 };
840 const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.EnumType, .{
841 .fields = try arena.dupe(*zir.Inst, fields.items),
842 }, .{
843 .layout = layout,
844 .tag_type = tag_type,
845 });
846 const enum_type = try arena.create(Type.Payload.Enum);
847 enum_type.* = .{
848 .analysis = .{
849 .queued = .{
850 .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) },
851 .inst = inst,
852 },
853 },
854 .scope = .{
855 .file_scope = scope.getFileScope(),
856 .ty = Type.initPayload(&enum_type.base),
857 },
858 };
859 break :blk Type.initPayload(&enum_type.base);
860 },
861 .Keyword_struct => blk: {
862 assert(node.init_arg_expr == .None);
863 const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.StructType, .{
864 .fields = try arena.dupe(*zir.Inst, fields.items),
865 }, .{
866 .layout = layout,
867 });
868 const struct_type = try arena.create(Type.Payload.Struct);
869 struct_type.* = .{
870 .analysis = .{
871 .queued = .{
872 .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) },
873 .inst = inst,
874 },
875 },
876 .scope = .{
877 .file_scope = scope.getFileScope(),
878 .ty = Type.initPayload(&struct_type.base),
879 },
880 };
881 break :blk Type.initPayload(&struct_type.base);
882 },
883 .Keyword_union => blk: {
884 const init_inst = switch (node.init_arg_expr) {
885 .Enum => |e| if (e) |t| try typeExpr(mod, &gen_scope.base, t) else null,
886 .None => null,
887 .Type => |t| try typeExpr(mod, &gen_scope.base, t),
888 };
889 const init_kind: zir.Inst.UnionType.InitKind = switch (node.init_arg_expr) {
890 .Enum => .enum_type,
891 .None => .none,
892 .Type => .tag_type,
893 };
894 const inst = try addZIRInst(mod, &gen_scope.base, src, zir.Inst.UnionType, .{
895 .fields = try arena.dupe(*zir.Inst, fields.items),
896 }, .{
897 .layout = layout,
898 .init_kind = init_kind,
899 .init_inst = init_inst,
900 });
901 const union_type = try arena.create(Type.Payload.Union);
902 union_type.* = .{
903 .analysis = .{
904 .queued = .{
905 .body = .{ .instructions = try arena.dupe(*zir.Inst, gen_scope.instructions.items) },
906 .inst = inst,
907 },
908 },
909 .scope = .{
910 .file_scope = scope.getFileScope(),
911 .ty = Type.initPayload(&union_type.base),
912 },
913 };
914 break :blk Type.initPayload(&union_type.base);
915 },
916 .Keyword_opaque => return mod.fail(scope, src, "TODO opaque containers", .{}),
917 else => unreachable,
918 };
919 const type_payload = try arena.create(Value.Payload.Ty);
920 type_payload.* = .{
921 .ty = container_type,
922 };
923 const decl = try mod.createContainerDecl(scope, node.kind_token, &decl_arena, .{
924 .ty = Type.initTag(.type),
925 .val = Value.initPayload(&type_payload.base),
926 });
927 return rlWrapPtr(mod, scope, rl, try addZIRInst(mod, scope, src, zir.Inst.DeclValInModule, .{ .decl = decl }, .{}));
928}
929
768930fn errorSetDecl(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node.ErrorSetDecl) InnerError!*zir.Inst {
769931 const tree = scope.tree();
770932 const src = tree.token_locs[node.error_token].start;
src/type.zig+4-4
......@@ -923,7 +923,7 @@ pub const Type = extern union {
923923 @panic("TODO abiAlignment error union");
924924 },
925925
926 .@"enum" => self.cast(Payload.Enum).?.abiAlignment(),
926 .@"enum" => self.cast(Payload.Enum).?.abiAlignment(target),
927927 .@"struct" => @panic("TODO"),
928928 .@"union" => @panic("TODO"),
929929
......@@ -3221,9 +3221,9 @@ pub const Type = extern union {
32213221 scope: *Module.Scope.Container,
32223222 };
32233223
3224 pub const Enum = @import("value/Enum.zig");
3225 pub const Struct = @import("value/Struct.zig");
3226 pub const Union = @import("value/Union.zig");
3224 pub const Enum = @import("type/Enum.zig");
3225 pub const Struct = @import("type/Struct.zig");
3226 pub const Union = @import("type/Union.zig");
32273227 };
32283228};
32293229
src/type/Enum.zig+6-6
......@@ -1,8 +1,10 @@
11const std = @import("std");
2const zir = @import("../zir.zig");
23const Value = @import("../value.zig").Value;
34const Type = @import("../type.zig").Type;
45const Module = @import("../Module.zig");
56const Scope = Module.Scope;
7const Enum = @This();
68
79base: Type.Payload = .{ .tag = .@"enum" },
810
......@@ -12,6 +14,7 @@ analysis: union(enum) {
1214 resolved: Size,
1315 failed,
1416},
17scope: Scope.Container,
1518
1619pub const Field = struct {
1720 value: Value,
......@@ -20,13 +23,10 @@ pub const Field = struct {
2023pub const Zir = struct {
2124 body: zir.Module.Body,
2225 inst: *zir.Inst,
23 arena: std.heap.ArenaAllocator.State,
2426};
2527
2628pub const Size = struct {
27 is_zero_bits: bool,
28 alignment: u32,
29 size: u32,
29 tag_type: Type,
3030 fields: std.AutoArrayHashMap([]const u8, Field),
3131};
3232
......@@ -45,11 +45,11 @@ pub fn resolve(self: *Enum, mod: *Module, scope: *Scope) !void {
4545}
4646
4747// TODO should this resolve the type or assert that it has already been resolved?
48pub fn abiAlignment(self: *Enum) u32 {
48pub fn abiAlignment(self: *Enum, target: std.Target) u32 {
4949 switch (self.analysis) {
5050 .queued => unreachable, // alignment has not been resolved
5151 .in_progress => unreachable, // alignment has not been resolved
5252 .failed => unreachable, // type resolution failed
53 .resolved => |r| return r.tag_type.abiAlignment(),
53 .resolved => |r| return r.tag_type.abiAlignment(target),
5454 }
5555}
src/type/Struct.zig+5-6
......@@ -1,8 +1,10 @@
11const std = @import("std");
2const zir = @import("../zir.zig");
23const Value = @import("../value.zig").Value;
34const Type = @import("../type.zig").Type;
45const Module = @import("../Module.zig");
56const Scope = Module.Scope;
7const Struct = @This();
68
79base: Type.Payload = .{ .tag = .@"struct" },
810
......@@ -11,7 +13,7 @@ analysis: union(enum) {
1113 zero_bits_in_progress,
1214 zero_bits: Zero,
1315 in_progress,
14 alignment: Align,
16 // alignment: Align,
1517 resolved: Size,
1618 failed,
1719},
......@@ -24,7 +26,6 @@ pub const Field = struct {
2426pub const Zir = struct {
2527 body: zir.Module.Body,
2628 inst: *zir.Inst,
27 arena: std.heap.ArenaAllocator.State,
2829};
2930
3031pub const Zero = struct {
......@@ -39,11 +40,11 @@ pub const Size = struct {
3940 fields: std.AutoArrayHashMap([]const u8, Field),
4041};
4142
42pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void {
43pub fn resolveZeroBits(self: *Struct, mod: *Module, scope: *Scope) !void {
4344 const zir = switch (self.analysis) {
4445 .failed => return error.AnalysisFail,
4546 .zero_bits_in_progress => {
46 return mod.fail(scope, src, "union '{}' depends on itself", .{});
47 return mod.fail(scope, src, "struct '{}' depends on itself", .{});
4748 },
4849 .queued => |zir| zir,
4950 else => return,
......@@ -53,5 +54,3 @@ pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void {
5354
5455 // TODO
5556}
56
57pub fn resolveSize(self: *Enum,)
\ No newline at end of file
src/type/Union.zig+4-5
......@@ -1,8 +1,10 @@
11const std = @import("std");
2const zir = @import("../zir.zig");
23const Value = @import("../value.zig").Value;
34const Type = @import("../type.zig").Type;
45const Module = @import("../Module.zig");
56const Scope = Module.Scope;
7const Union = @This();
68
79base: Type.Payload = .{ .tag = .@"struct" },
810
......@@ -11,7 +13,7 @@ analysis: union(enum) {
1113 zero_bits_in_progress,
1214 zero_bits: Zero,
1315 in_progress,
14 alignment: Align,
16 // alignment: Align,
1517 resolved: Size,
1618 failed,
1719},
......@@ -24,7 +26,6 @@ pub const Field = struct {
2426pub const Zir = struct {
2527 body: zir.Module.Body,
2628 inst: *zir.Inst,
27 arena: std.heap.ArenaAllocator.State,
2829};
2930
3031pub const Zero = struct {
......@@ -39,7 +40,7 @@ pub const Size = struct {
3940 fields: std.AutoArrayHashMap([]const u8, Field),
4041};
4142
42pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void {
43pub fn resolveZeroBits(self: *Union, mod: *Module, scope: *Scope) !void {
4344 const zir = switch (self.analysis) {
4445 .failed => return error.AnalysisFail,
4546 .zero_bits_in_progress => {
......@@ -53,5 +54,3 @@ pub fn resolveZeroBits(self: *Enum, mod: *Module, scope: *Scope) !void {
5354
5455 // TODO
5556}
56
57pub fn resolveSize(self: *Enum,)
\ No newline at end of file
src/zir.zig+15-10
......@@ -1084,12 +1084,13 @@ pub const Inst = struct {
10841084
10851085 positionals: struct {
10861086 bytes: []const u8,
1087 ty: ?*Inst,
1088 init: ?*Inst,
1089 alignment: ?*Inst,
1090 is_comptime: bool,
10911087 },
1092 kw_args: struct {},
1088 kw_args: struct {
1089 ty: ?*Inst = null,
1090 init: ?*Inst = null,
1091 alignment: ?*Inst = null,
1092 is_comptime: bool = false,
1093 },
10931094 };
10941095
10951096 pub const EnumType = struct {
......@@ -1125,13 +1126,17 @@ pub const Inst = struct {
11251126 fields: []*Inst,
11261127 },
11271128 kw_args: struct {
1128 init_expr: union(enum) {
1129 enum_type: ?*Inst,
1130 tag_type: *Inst,
1131 none,
1132 },
1129 init_inst: ?*Inst = null,
1130 init_kind: InitKind = .none,
11331131 layout: std.builtin.TypeInfo.ContainerLayout = .Auto,
11341132 },
1133
1134 // TODO error: values of type '(enum literal)' must be comptime known
1135 pub const InitKind = enum {
1136 enum_type,
1137 tag_type,
1138 none,
1139 };
11351140 };
11361141};
11371142
src/zir_sema.zig+8
......@@ -139,6 +139,14 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
139139 .switch_range => return analyzeInstSwitchRange(mod, scope, old_inst.castTag(.switch_range).?),
140140 .booland => return analyzeInstBoolOp(mod, scope, old_inst.castTag(.booland).?),
141141 .boolor => return analyzeInstBoolOp(mod, scope, old_inst.castTag(.boolor).?),
142
143 .container_field_named,
144 .container_field_typed,
145 .container_field,
146 .enum_type,
147 .union_type,
148 .struct_type,
149 => return mod.fail(scope, old_inst.src, "TODO analyze container instructions", .{}),
142150 }
143151}
144152