authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-08 20:37:19-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-08 20:37:19-07:00
log61b868f9a5345ab1dba3395107c7cdee3fd2989e
treebddaf5710f76aaf49edbee3251d1dd6d13995ccb
parent482b995a4963e045860c7fb1a4e11c48cf4de880

stage2: simplify Decl src_node field

Also fix "previous definition here" error notes to be correct.

6 files changed, 68 insertions(+), 103 deletions(-)

src/Module.zig+44-86
......@@ -150,9 +150,15 @@ pub const Decl = struct {
150150 /// The direct parent container of the Decl.
151151 /// Reference to externally owned memory.
152152 container: *Scope.Container,
153 /// The AST Node decl index or ZIR Inst index that contains this declaration.
153
154 /// An integer that can be checked against the corresponding incrementing
155 /// generation field of Module. This is used to determine whether `complete` status
156 /// represents pre- or post- re-analysis.
157 generation: u32,
158 /// The AST Node index or ZIR Inst index that contains this declaration.
154159 /// Must be recomputed when the corresponding source file is modified.
155 src_index: usize,
160 src_node: ast.Node.Index,
161
156162 /// The most recent value of the Decl after a successful semantic analysis.
157163 typed_value: union(enum) {
158164 never_succeeded: void,
......@@ -198,11 +204,6 @@ pub const Decl = struct {
198204 /// Whether the corresponding AST decl has a `pub` keyword.
199205 is_pub: bool,
200206
201 /// An integer that can be checked against the corresponding incrementing
202 /// generation field of Module. This is used to determine whether `complete` status
203 /// represents pre- or post- re-analysis.
204 generation: u32,
205
206207 /// Represents the position of the code in the output file.
207208 /// This is populated regardless of semantic analysis and code generation.
208209 link: link.File.LinkBlock,
......@@ -249,11 +250,11 @@ pub const Decl = struct {
249250 }
250251
251252 pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index {
252 return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.srcNode()));
253 return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.src_node));
253254 }
254255
255256 pub fn nodeIndexToRelative(decl: Decl, node_index: ast.Node.Index) i32 {
256 return @bitCast(i32, node_index) - @bitCast(i32, decl.srcNode());
257 return @bitCast(i32, node_index) - @bitCast(i32, decl.src_node);
257258 }
258259
259260 pub fn tokSrcLoc(decl: Decl, token_index: ast.TokenIndex) LazySrcLoc {
......@@ -271,14 +272,9 @@ pub const Decl = struct {
271272 };
272273 }
273274
274 pub fn srcNode(decl: Decl) u32 {
275 const tree = &decl.container.file_scope.tree;
276 return tree.rootDecls()[decl.src_index];
277 }
278
279275 pub fn srcToken(decl: Decl) u32 {
280276 const tree = &decl.container.file_scope.tree;
281 return tree.firstToken(decl.srcNode());
277 return tree.firstToken(decl.src_node);
282278 }
283279
284280 pub fn srcByteOffset(decl: Decl) u32 {
......@@ -2458,7 +2454,7 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
24582454 const tree = try mod.getAstTree(decl.container.file_scope);
24592455 const node_tags = tree.nodes.items(.tag);
24602456 const node_datas = tree.nodes.items(.data);
2461 const decl_node = tree.rootDecls()[decl.src_index];
2457 const decl_node = decl.src_node;
24622458 switch (node_tags[decl_node]) {
24632459 .fn_decl => {
24642460 const fn_proto = node_datas[decl_node].lhs;
......@@ -3292,7 +3288,7 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
32923288 var outdated_decls = std.AutoArrayHashMap(*Decl, void).init(mod.gpa);
32933289 defer outdated_decls.deinit();
32943290
3295 for (decls) |decl_node, decl_i| switch (node_tags[decl_node]) {
3291 for (decls) |decl_node| switch (node_tags[decl_node]) {
32963292 .fn_decl => {
32973293 const fn_proto = node_datas[decl_node].lhs;
32983294 const body = node_datas[decl_node].rhs;
......@@ -3304,7 +3300,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33043300 &deleted_decls,
33053301 &outdated_decls,
33063302 decl_node,
3307 decl_i,
33083303 tree.*,
33093304 body,
33103305 tree.fnProtoSimple(&params, fn_proto),
......@@ -3315,7 +3310,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33153310 &deleted_decls,
33163311 &outdated_decls,
33173312 decl_node,
3318 decl_i,
33193313 tree.*,
33203314 body,
33213315 tree.fnProtoMulti(fn_proto),
......@@ -3327,7 +3321,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33273321 &deleted_decls,
33283322 &outdated_decls,
33293323 decl_node,
3330 decl_i,
33313324 tree.*,
33323325 body,
33333326 tree.fnProtoOne(&params, fn_proto),
......@@ -3338,7 +3331,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33383331 &deleted_decls,
33393332 &outdated_decls,
33403333 decl_node,
3341 decl_i,
33423334 tree.*,
33433335 body,
33443336 tree.fnProto(fn_proto),
......@@ -3353,7 +3345,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33533345 &deleted_decls,
33543346 &outdated_decls,
33553347 decl_node,
3356 decl_i,
33573348 tree.*,
33583349 0,
33593350 tree.fnProtoSimple(&params, decl_node),
......@@ -3364,7 +3355,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33643355 &deleted_decls,
33653356 &outdated_decls,
33663357 decl_node,
3367 decl_i,
33683358 tree.*,
33693359 0,
33703360 tree.fnProtoMulti(decl_node),
......@@ -3376,7 +3366,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33763366 &deleted_decls,
33773367 &outdated_decls,
33783368 decl_node,
3379 decl_i,
33803369 tree.*,
33813370 0,
33823371 tree.fnProtoOne(&params, decl_node),
......@@ -3387,7 +3376,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33873376 &deleted_decls,
33883377 &outdated_decls,
33893378 decl_node,
3390 decl_i,
33913379 tree.*,
33923380 0,
33933381 tree.fnProto(decl_node),
......@@ -3398,7 +3386,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
33983386 &deleted_decls,
33993387 &outdated_decls,
34003388 decl_node,
3401 decl_i,
34023389 tree.*,
34033390 tree.globalVarDecl(decl_node),
34043391 ),
......@@ -3407,7 +3394,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
34073394 &deleted_decls,
34083395 &outdated_decls,
34093396 decl_node,
3410 decl_i,
34113397 tree.*,
34123398 tree.localVarDecl(decl_node),
34133399 ),
......@@ -3416,7 +3402,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
34163402 &deleted_decls,
34173403 &outdated_decls,
34183404 decl_node,
3419 decl_i,
34203405 tree.*,
34213406 tree.simpleVarDecl(decl_node),
34223407 ),
......@@ -3425,7 +3410,6 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
34253410 &deleted_decls,
34263411 &outdated_decls,
34273412 decl_node,
3428 decl_i,
34293413 tree.*,
34303414 tree.alignedVarDecl(decl_node),
34313415 ),
......@@ -3438,35 +3422,16 @@ pub fn analyzeContainer(mod: *Module, container_scope: *Scope.Container) !void {
34383422 const name_hash = container_scope.fullyQualifiedNameHash(name);
34393423 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
34403424
3441 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash);
3425 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash);
34423426 container_scope.decls.putAssumeCapacity(new_decl, {});
34433427 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
34443428 },
34453429
3446 .container_field_init => try mod.semaContainerField(
3447 container_scope,
3448 &deleted_decls,
3449 decl_node,
3450 decl_i,
3451 tree.*,
3452 tree.containerFieldInit(decl_node),
3453 ),
3454 .container_field_align => try mod.semaContainerField(
3455 container_scope,
3456 &deleted_decls,
3457 decl_node,
3458 decl_i,
3459 tree.*,
3460 tree.containerFieldAlign(decl_node),
3461 ),
3462 .container_field => try mod.semaContainerField(
3463 container_scope,
3464 &deleted_decls,
3465 decl_node,
3466 decl_i,
3467 tree.*,
3468 tree.containerField(decl_node),
3469 ),
3430 // Container fields are handled in AstGen.
3431 .container_field_init,
3432 .container_field_align,
3433 .container_field,
3434 => continue,
34703435
34713436 .test_decl => {
34723437 if (mod.comp.bin_file.options.is_test) {
......@@ -3508,7 +3473,6 @@ fn semaContainerFn(
35083473 deleted_decls: *std.AutoArrayHashMap(*Decl, void),
35093474 outdated_decls: *std.AutoArrayHashMap(*Decl, void),
35103475 decl_node: ast.Node.Index,
3511 decl_i: usize,
35123476 tree: ast.Tree,
35133477 body_node: ast.Node.Index,
35143478 fn_proto: ast.full.FnProto,
......@@ -3517,25 +3481,30 @@ fn semaContainerFn(
35173481 defer tracy.end();
35183482
35193483 // We will create a Decl for it regardless of analysis status.
3520 const name_tok = fn_proto.name_token orelse {
3484 const name_token = fn_proto.name_token orelse {
35213485 // This problem will go away with #1717.
35223486 @panic("TODO missing function name");
35233487 };
3524 const name = tree.tokenSlice(name_tok); // TODO use identifierTokenString
3488 const name = tree.tokenSlice(name_token); // TODO use identifierTokenString
35253489 const name_hash = container_scope.fullyQualifiedNameHash(name);
35263490 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
35273491 if (mod.decl_table.get(name_hash)) |decl| {
35283492 // Update the AST Node index of the decl, even if its contents are unchanged, it may
35293493 // have been re-ordered.
3530 decl.src_index = decl_i;
3494 const prev_src_node = decl.src_node;
3495 decl.src_node = decl_node;
35313496 if (deleted_decls.swapRemove(decl) == null) {
35323497 decl.analysis = .sema_failure;
35333498 const msg = try ErrorMsg.create(mod.gpa, .{
35343499 .container = .{ .file_scope = container_scope.file_scope },
3535 .lazy = .{ .token_abs = name_tok },
3500 .lazy = .{ .token_abs = name_token },
35363501 }, "redefinition of '{s}'", .{decl.name});
35373502 errdefer msg.destroy(mod.gpa);
3538 try mod.errNoteNonLazy(decl.srcLoc(), msg, "previous definition here", .{});
3503 const other_src_loc: SrcLoc = .{
3504 .container = .{ .file_scope = decl.container.file_scope },
3505 .lazy = .{ .node_abs = prev_src_node },
3506 };
3507 try mod.errNoteNonLazy(other_src_loc, msg, "previous definition here", .{});
35393508 try mod.failed_decls.putNoClobber(mod.gpa, decl, msg);
35403509 } else {
35413510 if (!srcHashEql(decl.contents_hash, contents_hash)) {
......@@ -3559,7 +3528,7 @@ fn semaContainerFn(
35593528 }
35603529 }
35613530 } else {
3562 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash);
3531 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash);
35633532 container_scope.decls.putAssumeCapacity(new_decl, {});
35643533 if (fn_proto.extern_export_token) |maybe_export_token| {
35653534 const token_tags = tree.tokens.items(.tag);
......@@ -3576,7 +3545,6 @@ fn semaContainerVar(
35763545 deleted_decls: *std.AutoArrayHashMap(*Decl, void),
35773546 outdated_decls: *std.AutoArrayHashMap(*Decl, void),
35783547 decl_node: ast.Node.Index,
3579 decl_i: usize,
35803548 tree: ast.Tree,
35813549 var_decl: ast.full.VarDecl,
35823550) !void {
......@@ -3590,7 +3558,8 @@ fn semaContainerVar(
35903558 if (mod.decl_table.get(name_hash)) |decl| {
35913559 // Update the AST Node index of the decl, even if its contents are unchanged, it may
35923560 // have been re-ordered.
3593 decl.src_index = decl_i;
3561 const prev_src_node = decl.src_node;
3562 decl.src_node = decl_node;
35943563 if (deleted_decls.swapRemove(decl) == null) {
35953564 decl.analysis = .sema_failure;
35963565 const msg = try ErrorMsg.create(mod.gpa, .{
......@@ -3598,14 +3567,18 @@ fn semaContainerVar(
35983567 .lazy = .{ .token_abs = name_token },
35993568 }, "redefinition of '{s}'", .{decl.name});
36003569 errdefer msg.destroy(mod.gpa);
3601 try mod.errNoteNonLazy(decl.srcLoc(), msg, "previous definition here", .{});
3570 const other_src_loc: SrcLoc = .{
3571 .container = .{ .file_scope = decl.container.file_scope },
3572 .lazy = .{ .node_abs = prev_src_node },
3573 };
3574 try mod.errNoteNonLazy(other_src_loc, msg, "previous definition here", .{});
36023575 try mod.failed_decls.putNoClobber(mod.gpa, decl, msg);
36033576 } else if (!srcHashEql(decl.contents_hash, contents_hash)) {
36043577 try outdated_decls.put(decl, {});
36053578 decl.contents_hash = contents_hash;
36063579 }
36073580 } else {
3608 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_i, name_hash, contents_hash);
3581 const new_decl = try mod.createNewDecl(&container_scope.base, name, decl_node, name_hash, contents_hash);
36093582 container_scope.decls.putAssumeCapacity(new_decl, {});
36103583 if (var_decl.extern_export_token) |maybe_export_token| {
36113584 const token_tags = tree.tokens.items(.tag);
......@@ -3616,21 +3589,6 @@ fn semaContainerVar(
36163589 }
36173590}
36183591
3619fn semaContainerField(
3620 mod: *Module,
3621 container_scope: *Scope.Container,
3622 deleted_decls: *std.AutoArrayHashMap(*Decl, void),
3623 decl_node: ast.Node.Index,
3624 decl_i: usize,
3625 tree: ast.Tree,
3626 field: ast.full.ContainerField,
3627) !void {
3628 const tracy = trace(@src());
3629 defer tracy.end();
3630
3631 log.err("TODO: analyze container field", .{});
3632}
3633
36343592pub fn deleteDecl(
36353593 mod: *Module,
36363594 decl: *Decl,
......@@ -3813,7 +3771,7 @@ fn markOutdatedDecl(mod: *Module, decl: *Decl) !void {
38133771fn allocateNewDecl(
38143772 mod: *Module,
38153773 scope: *Scope,
3816 src_index: usize,
3774 src_node: ast.Node.Index,
38173775 contents_hash: std.zig.SrcHash,
38183776) !*Decl {
38193777 // If we have emit-h then we must allocate a bigger structure to store the emit-h state.
......@@ -3829,7 +3787,7 @@ fn allocateNewDecl(
38293787 new_decl.* = .{
38303788 .name = "",
38313789 .container = scope.namespace(),
3832 .src_index = src_index,
3790 .src_node = src_node,
38333791 .typed_value = .{ .never_succeeded = {} },
38343792 .analysis = .unreferenced,
38353793 .deletion_flag = false,
......@@ -3860,12 +3818,12 @@ fn createNewDecl(
38603818 mod: *Module,
38613819 scope: *Scope,
38623820 decl_name: []const u8,
3863 src_index: usize,
3821 src_node: ast.Node.Index,
38643822 name_hash: Scope.NameHash,
38653823 contents_hash: std.zig.SrcHash,
38663824) !*Decl {
38673825 try mod.decl_table.ensureCapacity(mod.gpa, mod.decl_table.items().len + 1);
3868 const new_decl = try mod.allocateNewDecl(scope, src_index, contents_hash);
3826 const new_decl = try mod.allocateNewDecl(scope, src_node, contents_hash);
38693827 errdefer mod.gpa.destroy(new_decl);
38703828 new_decl.name = try mem.dupeZ(mod.gpa, u8, decl_name);
38713829 mod.decl_table.putAssumeCapacityNoClobber(name_hash, new_decl);
......@@ -4078,7 +4036,7 @@ pub fn createAnonymousDecl(
40784036 defer mod.gpa.free(name);
40794037 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
40804038 const src_hash: std.zig.SrcHash = undefined;
4081 const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_index, name_hash, src_hash);
4039 const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash);
40824040 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
40834041
40844042 decl_arena_state.* = decl_arena.state;
......@@ -4114,7 +4072,7 @@ pub fn createContainerDecl(
41144072 defer mod.gpa.free(name);
41154073 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
41164074 const src_hash: std.zig.SrcHash = undefined;
4117 const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_index, name_hash, src_hash);
4075 const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash);
41184076 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
41194077
41204078 decl_arena_state.* = decl_arena.state;
src/codegen.zig+1-1
......@@ -417,7 +417,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
417417 const node_datas = tree.nodes.items(.data);
418418 const token_starts = tree.tokens.items(.start);
419419
420 const fn_decl = tree.rootDecls()[module_fn.owner_decl.src_index];
420 const fn_decl = module_fn.owner_decl.src_node;
421421 assert(node_tags[fn_decl] == .fn_decl);
422422 const block = node_datas[fn_decl].rhs;
423423 const lbrace_src = token_starts[tree.firstToken(block)];
src/link/Elf.zig+2-4
......@@ -2228,10 +2228,9 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
22282228 const node_datas = tree.nodes.items(.data);
22292229 const token_starts = tree.tokens.items(.start);
22302230
2231 const file_ast_decls = tree.rootDecls();
22322231 // TODO Look into improving the performance here by adding a token-index-to-line
22332232 // lookup table. Currently this involves scanning over the source code for newlines.
2234 const fn_decl = file_ast_decls[decl.src_index];
2233 const fn_decl = decl.src_node;
22352234 assert(node_tags[fn_decl] == .fn_decl);
22362235 const block = node_datas[fn_decl].rhs;
22372236 const lbrace = tree.firstToken(block);
......@@ -2755,10 +2754,9 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
27552754 const node_datas = tree.nodes.items(.data);
27562755 const token_starts = tree.tokens.items(.start);
27572756
2758 const file_ast_decls = tree.rootDecls();
27592757 // TODO Look into improving the performance here by adding a token-index-to-line
27602758 // lookup table. Currently this involves scanning over the source code for newlines.
2761 const fn_decl = file_ast_decls[decl.src_index];
2759 const fn_decl = decl.src_node;
27622760 assert(node_tags[fn_decl] == .fn_decl);
27632761 const block = node_datas[fn_decl].rhs;
27642762 const lbrace = tree.firstToken(block);
src/link/MachO/DebugSymbols.zig+2-4
......@@ -909,10 +909,9 @@ pub fn updateDeclLineNumber(self: *DebugSymbols, module: *Module, decl: *const M
909909 const node_datas = tree.nodes.items(.data);
910910 const token_starts = tree.tokens.items(.start);
911911
912 const file_ast_decls = tree.rootDecls();
913912 // TODO Look into improving the performance here by adding a token-index-to-line
914913 // lookup table. Currently this involves scanning over the source code for newlines.
915 const fn_decl = file_ast_decls[decl.src_index];
914 const fn_decl = decl.src_node;
916915 assert(node_tags[fn_decl] == .fn_decl);
917916 const block = node_datas[fn_decl].rhs;
918917 const lbrace = tree.firstToken(block);
......@@ -959,10 +958,9 @@ pub fn initDeclDebugBuffers(
959958 const node_datas = tree.nodes.items(.data);
960959 const token_starts = tree.tokens.items(.start);
961960
962 const file_ast_decls = tree.rootDecls();
963961 // TODO Look into improving the performance here by adding a token-index-to-line
964962 // lookup table. Currently this involves scanning over the source code for newlines.
965 const fn_decl = file_ast_decls[decl.src_index];
963 const fn_decl = decl.src_node;
966964 assert(node_tags[fn_decl] == .fn_decl);
967965 const block = node_datas[fn_decl].rhs;
968966 const lbrace = tree.firstToken(block);
src/test.zig+5-7
......@@ -622,6 +622,7 @@ pub const TestContext = struct {
622622 var root_pkg: Package = .{
623623 .root_src_directory = .{ .path = tmp_dir_path, .handle = tmp.dir },
624624 .root_src_path = tmp_src_path,
625 .namespace_hash = Package.root_namespace_hash,
625626 };
626627
627628 const bin_name = try std.zig.binNameAlloc(arena, .{
......@@ -639,13 +640,10 @@ pub const TestContext = struct {
639640 .directory = emit_directory,
640641 .basename = bin_name,
641642 };
642 const emit_h: ?Compilation.EmitLoc = if (case.emit_h)
643 .{
644 .directory = emit_directory,
645 .basename = "test_case.h",
646 }
647 else
648 null;
643 const emit_h: ?Compilation.EmitLoc = if (case.emit_h) .{
644 .directory = emit_directory,
645 .basename = "test_case.h",
646 } else null;
649647 const comp = try Compilation.create(allocator, .{
650648 .local_cache_directory = zig_cache_directory,
651649 .global_cache_directory = global_cache_directory,
test/stage2/test.zig+14-1
......@@ -1040,9 +1040,22 @@ pub fn addCases(ctx: *TestContext) !void {
10401040 }
10411041
10421042 ctx.compileError("function redefinition", linux_x64,
1043 \\// dummy comment
10431044 \\fn entry() void {}
10441045 \\fn entry() void {}
1045 , &[_][]const u8{":2:4: error: redefinition of 'entry'"});
1046 , &[_][]const u8{
1047 ":3:4: error: redefinition of 'entry'",
1048 ":2:1: note: previous definition here",
1049 });
1050
1051 ctx.compileError("global variable redefinition", linux_x64,
1052 \\// dummy comment
1053 \\var foo = false;
1054 \\var foo = true;
1055 , &[_][]const u8{
1056 ":3:5: error: redefinition of 'foo'",
1057 ":2:1: note: previous definition here",
1058 });
10461059
10471060 ctx.compileError("compileError", linux_x64,
10481061 \\export fn _start() noreturn {