authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-09-03 14:58:47+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-09-03 15:06:45+03:00
log6f0126e9573a6bde9cbe5b113208e0a515b2eee7
treeada0f6c5b8f4493a5bba35241c4883fffa6b792c
parent1174cb15173208ead5f2ce828ade5b7d07ce6abe
signaturelock-open Commit is signed but in an unrecognized format.

stage2: split Scope.Container from Scope.File


3 files changed, 96 insertions(+), 58 deletions(-)

src-self-hosted/Module.zig+90-52
......@@ -125,7 +125,7 @@ pub const Decl = struct {
125125 /// mapping them to an address in the output file.
126126 /// Memory owned by this decl, using Module's allocator.
127127 name: [*:0]const u8,
128 /// The direct parent container of the Decl. This is either a `Scope.File` or `Scope.ZIRModule`.
128 /// The direct parent container of the Decl. This is either a `Scope.Container` or `Scope.ZIRModule`.
129129 /// Reference to externally owned memory.
130130 scope: *Scope,
131131 /// The AST Node decl index or ZIR Inst index that contains this declaration.
......@@ -217,9 +217,10 @@ pub const Decl = struct {
217217
218218 pub fn src(self: Decl) usize {
219219 switch (self.scope.tag) {
220 .file => {
221 const file = @fieldParentPtr(Scope.File, "base", self.scope);
222 const tree = file.contents.tree;
220 .container => {
221 const container = @fieldParentPtr(Scope.Container, "base", self.scope);
222 const tree = container.file_scope.contents.tree;
223 // TODO Container should have it's own decls()
223224 const decl_node = tree.root_node.decls()[self.src_index];
224225 return tree.token_locs[decl_node.firstToken()].start;
225226 },
......@@ -229,6 +230,7 @@ pub const Decl = struct {
229230 const src_decl = module.decls[self.src_index];
230231 return src_decl.inst.src;
231232 },
233 .file,
232234 .block => unreachable,
233235 .gen_zir => unreachable,
234236 .local_val => unreachable,
......@@ -359,6 +361,7 @@ pub const Scope = struct {
359361 .local_ptr => return self.cast(LocalPtr).?.gen_zir.arena,
360362 .zir_module => return &self.cast(ZIRModule).?.contents.module.arena.allocator,
361363 .file => unreachable,
364 .container => unreachable,
362365 }
363366 }
364367
......@@ -368,15 +371,16 @@ pub const Scope = struct {
368371 return switch (self.tag) {
369372 .block => self.cast(Block).?.decl,
370373 .gen_zir => self.cast(GenZIR).?.decl,
371 .local_val => return self.cast(LocalVal).?.gen_zir.decl,
372 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl,
374 .local_val => self.cast(LocalVal).?.gen_zir.decl,
375 .local_ptr => self.cast(LocalPtr).?.gen_zir.decl,
373376 .decl => self.cast(DeclAnalysis).?.decl,
374377 .zir_module => null,
375378 .file => null,
379 .container => null,
376380 };
377381 }
378382
379 /// Asserts the scope has a parent which is a ZIRModule or File and
383 /// Asserts the scope has a parent which is a ZIRModule or Container and
380384 /// returns it.
381385 pub fn namespace(self: *Scope) *Scope {
382386 switch (self.tag) {
......@@ -385,7 +389,8 @@ pub const Scope = struct {
385389 .local_val => return self.cast(LocalVal).?.gen_zir.decl.scope,
386390 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.scope,
387391 .decl => return self.cast(DeclAnalysis).?.decl.scope,
388 .zir_module, .file => return self,
392 .file => return &self.cast(File).?.root_container.base,
393 .zir_module, .container => return self,
389394 }
390395 }
391396
......@@ -399,8 +404,9 @@ pub const Scope = struct {
399404 .local_val => unreachable,
400405 .local_ptr => unreachable,
401406 .decl => unreachable,
407 .file => unreachable,
402408 .zir_module => return self.cast(ZIRModule).?.fullyQualifiedNameHash(name),
403 .file => return self.cast(File).?.fullyQualifiedNameHash(name),
409 .container => return self.cast(Container).?.fullyQualifiedNameHash(name),
404410 }
405411 }
406412
......@@ -409,11 +415,12 @@ pub const Scope = struct {
409415 switch (self.tag) {
410416 .file => return self.cast(File).?.contents.tree,
411417 .zir_module => unreachable,
412 .decl => return self.cast(DeclAnalysis).?.decl.scope.cast(File).?.contents.tree,
413 .block => return self.cast(Block).?.decl.scope.cast(File).?.contents.tree,
414 .gen_zir => return self.cast(GenZIR).?.decl.scope.cast(File).?.contents.tree,
415 .local_val => return self.cast(LocalVal).?.gen_zir.decl.scope.cast(File).?.contents.tree,
416 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.scope.cast(File).?.contents.tree,
418 .decl => return self.cast(DeclAnalysis).?.decl.scope.cast(Container).?.file_scope.contents.tree,
419 .block => return self.cast(Block).?.decl.scope.cast(Container).?.file_scope.contents.tree,
420 .gen_zir => return self.cast(GenZIR).?.decl.scope.cast(Container).?.file_scope.contents.tree,
421 .local_val => return self.cast(LocalVal).?.gen_zir.decl.scope.cast(Container).?.file_scope.contents.tree,
422 .local_ptr => return self.cast(LocalPtr).?.gen_zir.decl.scope.cast(Container).?.file_scope.contents.tree,
423 .container => return self.cast(Container).?.file_scope.contents.tree,
417424 }
418425 }
419426
......@@ -427,13 +434,15 @@ pub const Scope = struct {
427434 .decl => unreachable,
428435 .zir_module => unreachable,
429436 .file => unreachable,
437 .container => unreachable,
430438 };
431439 }
432440
433 /// Asserts the scope has a parent which is a ZIRModule or File and
441 /// Asserts the scope has a parent which is a ZIRModule, Contaienr or File and
434442 /// returns the sub_file_path field.
435443 pub fn subFilePath(base: *Scope) []const u8 {
436444 switch (base.tag) {
445 .container => return @fieldParentPtr(Container, "base", base).file_scope.sub_file_path,
437446 .file => return @fieldParentPtr(File, "base", base).sub_file_path,
438447 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).sub_file_path,
439448 .block => unreachable,
......@@ -453,11 +462,13 @@ pub const Scope = struct {
453462 .local_val => unreachable,
454463 .local_ptr => unreachable,
455464 .decl => unreachable,
465 .container => unreachable,
456466 }
457467 }
458468
459469 pub fn getSource(base: *Scope, module: *Module) ![:0]const u8 {
460470 switch (base.tag) {
471 .container => return @fieldParentPtr(Container, "base", base).file_scope.getSource(module),
461472 .file => return @fieldParentPtr(File, "base", base).getSource(module),
462473 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).getSource(module),
463474 .gen_zir => unreachable,
......@@ -471,8 +482,9 @@ pub const Scope = struct {
471482 /// Asserts the scope is a namespace Scope and removes the Decl from the namespace.
472483 pub fn removeDecl(base: *Scope, child: *Decl) void {
473484 switch (base.tag) {
474 .file => return @fieldParentPtr(File, "base", base).removeDecl(child),
485 .container => return @fieldParentPtr(Container, "base", base).removeDecl(child),
475486 .zir_module => return @fieldParentPtr(ZIRModule, "base", base).removeDecl(child),
487 .file => unreachable,
476488 .block => unreachable,
477489 .gen_zir => unreachable,
478490 .local_val => unreachable,
......@@ -499,6 +511,7 @@ pub const Scope = struct {
499511 .local_val => unreachable,
500512 .local_ptr => unreachable,
501513 .decl => unreachable,
514 .container => unreachable,
502515 }
503516 }
504517
......@@ -515,6 +528,8 @@ pub const Scope = struct {
515528 zir_module,
516529 /// .zig source code.
517530 file,
531 /// struct, enum or union, every .file contains one of these.
532 container,
518533 block,
519534 decl,
520535 gen_zir,
......@@ -522,6 +537,38 @@ pub const Scope = struct {
522537 local_ptr,
523538 };
524539
540 pub const Container = struct {
541 pub const base_tag: Tag = .container;
542 base: Scope = Scope{ .tag = base_tag },
543
544 file_scope: *Scope.File,
545
546 /// Direct children of the file.
547 decls: ArrayListUnmanaged(*Decl),
548
549 // TODO implement container types and put this in a status union
550 // ty: Type
551
552 pub fn deinit(self: *Container, gpa: *Allocator) void {
553 self.decls.deinit(gpa);
554 self.* = undefined;
555 }
556
557 pub fn removeDecl(self: *Container, child: *Decl) void {
558 for (self.decls.items) |item, i| {
559 if (item == child) {
560 _ = self.decls.swapRemove(i);
561 return;
562 }
563 }
564 }
565
566 pub fn fullyQualifiedNameHash(self: *Container, name: []const u8) NameHash {
567 // TODO container scope qualified names.
568 return std.zig.hashSrc(name);
569 }
570 };
571
525572 pub const File = struct {
526573 pub const base_tag: Tag = .file;
527574 base: Scope = Scope{ .tag = base_tag },
......@@ -544,8 +591,7 @@ pub const Scope = struct {
544591 loaded_success,
545592 },
546593
547 /// Direct children of the file.
548 decls: ArrayListUnmanaged(*Decl),
594 root_container: Container,
549595
550596 pub fn unload(self: *File, gpa: *Allocator) void {
551597 switch (self.status) {
......@@ -569,20 +615,11 @@ pub const Scope = struct {
569615 }
570616
571617 pub fn deinit(self: *File, gpa: *Allocator) void {
572 self.decls.deinit(gpa);
618 self.root_container.deinit(gpa);
573619 self.unload(gpa);
574620 self.* = undefined;
575621 }
576622
577 pub fn removeDecl(self: *File, child: *Decl) void {
578 for (self.decls.items) |item, i| {
579 if (item == child) {
580 _ = self.decls.swapRemove(i);
581 return;
582 }
583 }
584 }
585
586623 pub fn dumpSrc(self: *File, src: usize) void {
587624 const loc = std.zig.findLineColumn(self.source.bytes, src);
588625 std.debug.print("{}:{}:{}\n", .{ self.sub_file_path, loc.line + 1, loc.column + 1 });
......@@ -604,11 +641,6 @@ pub const Scope = struct {
604641 .bytes => |bytes| return bytes,
605642 }
606643 }
607
608 pub fn fullyQualifiedNameHash(self: *File, name: []const u8) NameHash {
609 // We don't have struct scopes yet so this is currently just a simple name hash.
610 return std.zig.hashSrc(name);
611 }
612644 };
613645
614646 pub const ZIRModule = struct {
......@@ -861,7 +893,10 @@ pub fn init(gpa: *Allocator, options: InitOptions) !Module {
861893 .source = .{ .unloaded = {} },
862894 .contents = .{ .not_available = {} },
863895 .status = .never_loaded,
864 .decls = .{},
896 .root_container = .{
897 .file_scope = root_scope,
898 .decls = .{},
899 },
865900 };
866901 break :blk &root_scope.base;
867902 } else if (mem.endsWith(u8, options.root_pkg.root_src_path, ".zir")) {
......@@ -969,7 +1004,7 @@ pub fn update(self: *Module) !void {
9691004 // to force a refresh we unload now.
9701005 if (self.root_scope.cast(Scope.File)) |zig_file| {
9711006 zig_file.unload(self.gpa);
972 self.analyzeRootSrcFile(zig_file) catch |err| switch (err) {
1007 self.analyzeContainer(&zig_file.root_container) catch |err| switch (err) {
9731008 error.AnalysisFail => {
9741009 assert(self.totalErrorCount() != 0);
9751010 },
......@@ -1237,8 +1272,8 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
12371272 const tracy = trace(@src());
12381273 defer tracy.end();
12391274
1240 const file_scope = decl.scope.cast(Scope.File).?;
1241 const tree = try self.getAstTree(file_scope);
1275 const container_scope = decl.scope.cast(Scope.Container).?;
1276 const tree = try self.getAstTree(container_scope);
12421277 const ast_node = tree.root_node.decls()[decl.src_index];
12431278 switch (ast_node.tag) {
12441279 .FnProto => {
......@@ -1698,10 +1733,12 @@ fn getSrcModule(self: *Module, root_scope: *Scope.ZIRModule) !*zir.Module {
16981733 }
16991734}
17001735
1701fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {
1736fn getAstTree(self: *Module, container_scope: *Scope.Container) !*ast.Tree {
17021737 const tracy = trace(@src());
17031738 defer tracy.end();
17041739
1740 const root_scope = container_scope.file_scope;
1741
17051742 switch (root_scope.status) {
17061743 .never_loaded, .unloaded_success => {
17071744 try self.failed_files.ensureCapacity(self.gpa, self.failed_files.items().len + 1);
......@@ -1743,24 +1780,24 @@ fn getAstTree(self: *Module, root_scope: *Scope.File) !*ast.Tree {
17431780 }
17441781}
17451782
1746fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
1783fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void {
17471784 const tracy = trace(@src());
17481785 defer tracy.end();
17491786
17501787 // We may be analyzing it for the first time, or this may be
17511788 // an incremental update. This code handles both cases.
1752 const tree = try self.getAstTree(root_scope);
1789 const tree = try self.getAstTree(container_scope);
17531790 const decls = tree.root_node.decls();
17541791
17551792 try self.work_queue.ensureUnusedCapacity(decls.len);
1756 try root_scope.decls.ensureCapacity(self.gpa, decls.len);
1793 try container_scope.decls.ensureCapacity(self.gpa, decls.len);
17571794
17581795 // Keep track of the decls that we expect to see in this file so that
17591796 // we know which ones have been deleted.
17601797 var deleted_decls = std.AutoArrayHashMap(*Decl, void).init(self.gpa);
17611798 defer deleted_decls.deinit();
1762 try deleted_decls.ensureCapacity(root_scope.decls.items.len);
1763 for (root_scope.decls.items) |file_decl| {
1799 try deleted_decls.ensureCapacity(container_scope.decls.items.len);
1800 for (container_scope.decls.items) |file_decl| {
17641801 deleted_decls.putAssumeCapacityNoClobber(file_decl, {});
17651802 }
17661803
......@@ -1773,7 +1810,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
17731810
17741811 const name_loc = tree.token_locs[name_tok];
17751812 const name = tree.tokenSliceLoc(name_loc);
1776 const name_hash = root_scope.fullyQualifiedNameHash(name);
1813 const name_hash = container_scope.fullyQualifiedNameHash(name);
17771814 const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl));
17781815 if (self.decl_table.get(name_hash)) |decl| {
17791816 // Update the AST Node index of the decl, even if its contents are unchanged, it may
......@@ -1801,8 +1838,8 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
18011838 }
18021839 }
18031840 } else {
1804 const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash);
1805 root_scope.decls.appendAssumeCapacity(new_decl);
1841 const new_decl = try self.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash);
1842 container_scope.decls.appendAssumeCapacity(new_decl);
18061843 if (fn_proto.getExternExportInlineToken()) |maybe_export_token| {
18071844 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
18081845 self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
......@@ -1812,7 +1849,7 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
18121849 } else if (src_decl.castTag(.VarDecl)) |var_decl| {
18131850 const name_loc = tree.token_locs[var_decl.name_token];
18141851 const name = tree.tokenSliceLoc(name_loc);
1815 const name_hash = root_scope.fullyQualifiedNameHash(name);
1852 const name_hash = container_scope.fullyQualifiedNameHash(name);
18161853 const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl));
18171854 if (self.decl_table.get(name_hash)) |decl| {
18181855 // Update the AST Node index of the decl, even if its contents are unchanged, it may
......@@ -1828,8 +1865,8 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
18281865 decl.contents_hash = contents_hash;
18291866 }
18301867 } else {
1831 const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash);
1832 root_scope.decls.appendAssumeCapacity(new_decl);
1868 const new_decl = try self.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash);
1869 container_scope.decls.appendAssumeCapacity(new_decl);
18331870 if (var_decl.getExternExportToken()) |maybe_export_token| {
18341871 if (tree.token_ids[maybe_export_token] == .Keyword_export) {
18351872 self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
......@@ -1841,11 +1878,11 @@ fn analyzeRootSrcFile(self: *Module, root_scope: *Scope.File) !void {
18411878 const name = try std.fmt.allocPrint(self.gpa, "__comptime_{}", .{name_index});
18421879 defer self.gpa.free(name);
18431880
1844 const name_hash = root_scope.fullyQualifiedNameHash(name);
1881 const name_hash = container_scope.fullyQualifiedNameHash(name);
18451882 const contents_hash = std.zig.hashSrc(tree.getNodeSource(src_decl));
18461883
1847 const new_decl = try self.createNewDecl(&root_scope.base, name, decl_i, name_hash, contents_hash);
1848 root_scope.decls.appendAssumeCapacity(new_decl);
1884 const new_decl = try self.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash);
1885 container_scope.decls.appendAssumeCapacity(new_decl);
18491886 self.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
18501887 } else if (src_decl.castTag(.ContainerField)) |container_field| {
18511888 log.err("TODO: analyze container field", .{});
......@@ -3124,6 +3161,7 @@ fn failWithOwnedErrorMsg(self: *Module, scope: *Scope, src: usize, err_msg: *Err
31243161 self.failed_files.putAssumeCapacityNoClobber(scope, err_msg);
31253162 },
31263163 .file => unreachable,
3164 .container => unreachable,
31273165 }
31283166 return error.AnalysisFail;
31293167}
src-self-hosted/codegen.zig+2-2
......@@ -436,8 +436,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
436436 try branch_stack.append(.{});
437437
438438 const src_data: struct {lbrace_src: usize, rbrace_src: usize, source: []const u8} = blk: {
439 if (module_fn.owner_decl.scope.cast(Module.Scope.File)) |scope_file| {
440 const tree = scope_file.contents.tree;
439 if (module_fn.owner_decl.scope.cast(Module.Scope.Container)) |container_scope| {
440 const tree = container_scope.file_scope.contents.tree;
441441 const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?;
442442 const block = fn_proto.getBodyNode().?.castTag(.Block).?;
443443 const lbrace_src = tree.token_locs[block.lbrace].start;
src-self-hosted/link/Elf.zig+4-4
......@@ -1656,8 +1656,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
16561656 try dbg_line_buffer.ensureCapacity(26);
16571657
16581658 const line_off: u28 = blk: {
1659 if (decl.scope.cast(Module.Scope.File)) |scope_file| {
1660 const tree = scope_file.contents.tree;
1659 if (decl.scope.cast(Module.Scope.Container)) |container_scope| {
1660 const tree = container_scope.file_scope.contents.tree;
16611661 const file_ast_decls = tree.root_node.decls();
16621662 // TODO Look into improving the performance here by adding a token-index-to-line
16631663 // lookup table. Currently this involves scanning over the source code for newlines.
......@@ -2157,8 +2157,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
21572157 const tracy = trace(@src());
21582158 defer tracy.end();
21592159
2160 const scope_file = decl.scope.cast(Module.Scope.File).?;
2161 const tree = scope_file.contents.tree;
2160 const container_scope = decl.scope.cast(Module.Scope.Container).?;
2161 const tree = container_scope.file_scope.contents.tree;
21622162 const file_ast_decls = tree.root_node.decls();
21632163 // TODO Look into improving the performance here by adding a token-index-to-line
21642164 // lookup table. Currently this involves scanning over the source code for newlines.