From 8387307807434cf151d72a7dfb5b7da4863b2192 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 15 Apr 2021 20:34:21 -0700 Subject: [PATCH] AstGen: implement global variable decls --- BRANCH_TODO | 548 +++++-------------------------------------------- src/AstGen.zig | 111 ++++++++-- src/Module.zig | 7 +- 3 files changed, 154 insertions(+), 512 deletions(-) diff --git a/BRANCH_TODO b/BRANCH_TODO index 73379f129b..949200a334 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -1,4 +1,5 @@ * get rid of failed_root_src_file + * get rid of Scope.DeclRef * handle decl collision with usingnamespace * the decl doing the looking up needs to create a decl dependency on each usingnamespace decl @@ -106,42 +107,6 @@ fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenInd } - // Detect which source files changed. - for (module.import_table.items()) |entry| { - const file = entry.value; - var f = try file.pkg.root_src_directory.handle.openFile(file.sub_file_path, .{}); - defer f.close(); - - // TODO handle error here by populating a retryable compile error - const stat = try f.stat(); - const unchanged_metadata = - stat.size == file.stat_size and - stat.mtime == file.stat_mtime and - stat.inode == file.stat_inode; - - if (unchanged_metadata) { - log.debug("unmodified metadata of file: {s}", .{file.sub_file_path}); - continue; - } - - log.debug("metadata changed: {s}", .{file.sub_file_path}); - if (file.status == .unloaded_parse_failure) { - module.failed_files.swapRemove(file).?.value.destroy(module.gpa); - } - - file.unload(module.gpa); - // TODO handle error here by populating a retryable compile error - try file.finishGettingSource(module.gpa, f, stat); - - module.analyzeFile(file) catch |err| switch (err) { - error.OutOfMemory => return error.OutOfMemory, - error.AnalysisFail => continue, - else => |e| return e, - }; - } - - - const parent_name_hash: Scope.NameHash = if (found_pkg) |pkg| pkg.namespace_hash else @@ -256,68 +221,6 @@ fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenInd -pub fn getAstTree(mod: *Module, file: *Scope.File) !*const ast.Tree { - const tracy = trace(@src()); - defer tracy.end(); - - if (file.tree_loaded) { - return &file.tree; - } - - switch (file.status) { - .never_loaded, .success, .retryable_failure => {}, - .parse_failure, .astgen_failure => return error.AnalysisFail, - } - - switch (file.status) { - .never_loaded, .unloaded_success => { - const gpa = mod.gpa; - - try mod.failed_files.ensureCapacity(gpa, mod.failed_files.items().len + 1); - - const source = try file.getSource(gpa); - - var keep_tree = false; - file.tree = try std.zig.parse(gpa, source); - defer if (!keep_tree) file.tree.deinit(gpa); - - const tree = &file.tree; - - if (tree.errors.len != 0) { - const parse_err = tree.errors[0]; - - var msg = std.ArrayList(u8).init(gpa); - defer msg.deinit(); - - const token_starts = tree.tokens.items(.start); - - try tree.renderError(parse_err, msg.writer()); - const err_msg = try gpa.create(ErrorMsg); - err_msg.* = .{ - .src_loc = .{ - .container = .{ .file_scope = file }, - .lazy = .{ .byte_abs = token_starts[parse_err.token] }, - }, - .msg = msg.toOwnedSlice(), - }; - - mod.failed_files.putAssumeCapacityNoClobber(file, err_msg); - file.status = .unloaded_parse_failure; - return error.AnalysisFail; - } - - file.status = .success; - file.tree_loaded = true; - keep_tree = true; - - return tree; - }, - - .unloaded_parse_failure => return error.AnalysisFail, - - .success => return &file.tree, - } -} @@ -510,131 +413,6 @@ fn astgenAndSemaFn( body_node: ast.Node.Index, fn_proto: ast.full.FnProto, ) !bool { - var fn_type_sema: Sema = .{ - .mod = mod, - .gpa = mod.gpa, - .arena = &decl_arena.allocator, - .code = fn_type_code, - .inst_map = try fn_type_scope_arena.allocator.alloc(*ir.Inst, fn_type_code.instructions.len), - .owner_decl = decl, - .namespace = decl.namespace, - .func = null, - .owner_func = null, - .param_inst_list = &.{}, - }; - var block_scope: Scope.Block = .{ - .parent = null, - .sema = &fn_type_sema, - .src_decl = decl, - .instructions = .{}, - .inlining = null, - .is_comptime = true, - }; - defer block_scope.instructions.deinit(mod.gpa); - - const fn_type = try fn_type_sema.rootAsType(&block_scope); - if (body_node == 0) { - // Extern function. - var type_changed = true; - if (decl.typedValueManaged()) |tvm| { - type_changed = !tvm.typed_value.ty.eql(fn_type); - - tvm.deinit(mod.gpa); - } - const fn_val = try Value.Tag.extern_fn.create(&decl_arena.allocator, decl); - - decl_arena_state.* = decl_arena.state; - decl.typed_value = .{ - .most_recent = .{ - .typed_value = .{ .ty = fn_type, .val = fn_val }, - .arena = decl_arena_state, - }, - }; - decl.analysis = .complete; - decl.generation = mod.generation; - - try mod.comp.bin_file.allocateDeclIndexes(decl); - try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl }); - - if (type_changed and mod.emit_h != null) { - try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl }); - } - - return type_changed; - } - - if (fn_type.fnIsVarArgs()) { - return mod.failNode(&block_scope.base, fn_proto.ast.fn_token, "non-extern function is variadic", .{}); - } - - const new_func = try decl_arena.allocator.create(Fn); - const fn_payload = try decl_arena.allocator.create(Value.Payload.Function); - - const fn_zir: Zir = blk: { - // We put the ZIR inside the Decl arena. - var astgen = try AstGen.init(mod, decl, &decl_arena.allocator); - astgen.ref_start_index = @intCast(u32, Zir.Inst.Ref.typed_value_map.len + param_count); - defer astgen.deinit(); - - var gen_scope: Scope.GenZir = .{ - .force_comptime = false, - .parent = &decl.namespace.base, - .astgen = &astgen, - }; - defer gen_scope.instructions.deinit(mod.gpa); - - // Iterate over the parameters. We put the param names as the first N - // items inside `extra` so that debug info later can refer to the parameter names - // even while the respective source code is unloaded. - try astgen.extra.ensureCapacity(mod.gpa, param_count); - - var params_scope = &gen_scope.base; - var i: usize = 0; - var it = fn_proto.iterate(tree); - while (it.next()) |param| : (i += 1) { - const name_token = param.name_token.?; - const param_name = try mod.identifierTokenString(&gen_scope.base, name_token); - const sub_scope = try decl_arena.allocator.create(Scope.LocalVal); - sub_scope.* = .{ - .parent = params_scope, - .gen_zir = &gen_scope, - .name = param_name, - // Implicit const list first, then implicit arg list. - .inst = @intToEnum(Zir.Inst.Ref, @intCast(u32, Zir.Inst.Ref.typed_value_map.len + i)), - .src = decl.tokSrcLoc(name_token), - }; - params_scope = &sub_scope.base; - - // Additionally put the param name into `string_bytes` and reference it with - // `extra` so that we have access to the data in codegen, for debug info. - const str_index = @intCast(u32, astgen.string_bytes.items.len); - astgen.extra.appendAssumeCapacity(str_index); - const used_bytes = astgen.string_bytes.items.len; - try astgen.string_bytes.ensureCapacity(mod.gpa, used_bytes + param_name.len + 1); - astgen.string_bytes.appendSliceAssumeCapacity(param_name); - astgen.string_bytes.appendAssumeCapacity(0); - } - - _ = try AstGen.expr(&gen_scope, params_scope, .none, body_node); - - if (gen_scope.instructions.items.len == 0 or - !astgen.instructions.items(.tag)[gen_scope.instructions.items.len - 1] - .isNoReturn()) - { - // astgen uses result location semantics to coerce return operands. - // Since we are adding the return instruction here, we must handle the coercion. - // We do this by using the `ret_coerce` instruction. - _ = try gen_scope.addUnTok(.ret_coerce, .void_value, tree.lastToken(body_node)); - } - - const code = try gen_scope.finish(); - if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { - code.dump(mod.gpa, "fn_body", &gen_scope.base, param_count) catch {}; - } - - break :blk code; - }; - const is_inline = fn_type.fnCallingConvention() == .Inline; const anal_state: Fn.Analysis = if (is_inline) .inline_only else .queued; @@ -716,264 +494,11 @@ fn astgenAndSemaVarDecl( tree: ast.Tree, var_decl: ast.full.VarDecl, ) !bool { - const tracy = trace(@src()); - defer tracy.end(); - - decl.analysis = .in_progress; - decl.is_pub = var_decl.visib_token != null; - const token_tags = tree.tokens.items(.tag); - // We need the memory for the Type to go into the arena for the Decl - var decl_arena = std.heap.ArenaAllocator.init(mod.gpa); - errdefer decl_arena.deinit(); - const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); - - // Used for simple error reporting. - var decl_scope: Scope.DeclRef = .{ .decl = decl }; - - const is_extern = blk: { - const maybe_extern_token = var_decl.extern_export_token orelse break :blk false; - break :blk token_tags[maybe_extern_token] == .keyword_extern; - }; - - if (var_decl.lib_name) |lib_name| { - assert(is_extern); - return mod.failTok(&decl_scope.base, lib_name, "TODO implement function library name", .{}); - } - const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; - const is_threadlocal = if (var_decl.threadlocal_token) |some| blk: { - if (!is_mutable) { - return mod.failTok(&decl_scope.base, some, "threadlocal variable cannot be constant", .{}); - } - break :blk true; - } else false; - assert(var_decl.comptime_token == null); - if (var_decl.ast.align_node != 0) { - return mod.failNode( - &decl_scope.base, - var_decl.ast.align_node, - "TODO implement function align expression", - .{}, - ); - } - if (var_decl.ast.section_node != 0) { - return mod.failNode( - &decl_scope.base, - var_decl.ast.section_node, - "TODO implement function section expression", - .{}, - ); - } - - const var_info: struct { ty: Type, val: ?Value } = if (var_decl.ast.init_node != 0) vi: { - if (is_extern) { - return mod.failNode( - &decl_scope.base, - var_decl.ast.init_node, - "extern variables have no initializers", - .{}, - ); - } - - var gen_scope_arena = std.heap.ArenaAllocator.init(mod.gpa); - defer gen_scope_arena.deinit(); - - var astgen = try AstGen.init(mod, decl, &gen_scope_arena.allocator); - defer astgen.deinit(); - - var gen_scope: Scope.GenZir = .{ - .force_comptime = true, - .parent = &decl.namespace.base, - .astgen = &astgen, - }; - defer gen_scope.instructions.deinit(mod.gpa); - - const init_result_loc: AstGen.ResultLoc = if (var_decl.ast.type_node != 0) .{ - .ty = try AstGen.expr(&gen_scope, &gen_scope.base, .{ .ty = .type_type }, var_decl.ast.type_node), - } else .none; - - const init_inst = try AstGen.comptimeExpr( - &gen_scope, - &gen_scope.base, - init_result_loc, - var_decl.ast.init_node, - ); - _ = try gen_scope.addBreak(.break_inline, 0, init_inst); - var code = try gen_scope.finish(); - defer code.deinit(mod.gpa); - if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { - code.dump(mod.gpa, "var_init", &gen_scope.base, 0) catch {}; - } - - var sema: Sema = .{ - .mod = mod, - .gpa = mod.gpa, - .arena = &gen_scope_arena.allocator, - .code = code, - .inst_map = try gen_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len), - .owner_decl = decl, - .namespace = decl.namespace, - .func = null, - .owner_func = null, - .param_inst_list = &.{}, - }; - var block_scope: Scope.Block = .{ - .parent = null, - .sema = &sema, - .src_decl = decl, - .instructions = .{}, - .inlining = null, - .is_comptime = true, - }; - defer block_scope.instructions.deinit(mod.gpa); - - const init_inst_zir_ref = try sema.rootAsRef(&block_scope); - // The result location guarantees the type coercion. - const analyzed_init_inst = try sema.resolveInst(init_inst_zir_ref); - // The is_comptime in the Scope.Block guarantees the result is comptime-known. - const val = analyzed_init_inst.value().?; - - break :vi .{ - .ty = try analyzed_init_inst.ty.copy(&decl_arena.allocator), - .val = try val.copy(&decl_arena.allocator), - }; - } else if (!is_extern) { - return mod.failTok( - &decl_scope.base, - var_decl.ast.mut_token, - "variables must be initialized", - .{}, - ); - } else if (var_decl.ast.type_node != 0) vi: { - var type_scope_arena = std.heap.ArenaAllocator.init(mod.gpa); - defer type_scope_arena.deinit(); - - var astgen = try AstGen.init(mod, decl, &type_scope_arena.allocator); - defer astgen.deinit(); - - var type_scope: Scope.GenZir = .{ - .force_comptime = true, - .parent = &decl.namespace.base, - .astgen = &astgen, - }; - defer type_scope.instructions.deinit(mod.gpa); - - const var_type = try AstGen.typeExpr(&type_scope, &type_scope.base, var_decl.ast.type_node); - _ = try type_scope.addBreak(.break_inline, 0, var_type); - - var code = try type_scope.finish(); - defer code.deinit(mod.gpa); - if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { - code.dump(mod.gpa, "var_type", &type_scope.base, 0) catch {}; - } - - var sema: Sema = .{ - .mod = mod, - .gpa = mod.gpa, - .arena = &type_scope_arena.allocator, - .code = code, - .inst_map = try type_scope_arena.allocator.alloc(*ir.Inst, code.instructions.len), - .owner_decl = decl, - .namespace = decl.namespace, - .func = null, - .owner_func = null, - .param_inst_list = &.{}, - }; - var block_scope: Scope.Block = .{ - .parent = null, - .sema = &sema, - .src_decl = decl, - .instructions = .{}, - .inlining = null, - .is_comptime = true, - }; - defer block_scope.instructions.deinit(mod.gpa); - - const ty = try sema.rootAsType(&block_scope); - - break :vi .{ - .ty = try ty.copy(&decl_arena.allocator), - .val = null, - }; - } else { - return mod.failTok( - &decl_scope.base, - var_decl.ast.mut_token, - "unable to infer variable type", - .{}, - ); - }; - - if (is_mutable and !var_info.ty.isValidVarType(is_extern)) { - return mod.failTok( - &decl_scope.base, - var_decl.ast.mut_token, - "variable of type '{}' must be const", - .{var_info.ty}, - ); - } - - var type_changed = true; - if (decl.typedValueManaged()) |tvm| { - type_changed = !tvm.typed_value.ty.eql(var_info.ty); - - tvm.deinit(mod.gpa); - } - - const new_variable = try decl_arena.allocator.create(Var); - new_variable.* = .{ - .owner_decl = decl, - .init = var_info.val orelse undefined, - .is_extern = is_extern, - .is_mutable = is_mutable, - .is_threadlocal = is_threadlocal, - }; - const var_val = try Value.Tag.variable.create(&decl_arena.allocator, new_variable); - - decl_arena_state.* = decl_arena.state; - decl.typed_value = .{ - .most_recent = .{ - .typed_value = .{ - .ty = var_info.ty, - .val = var_val, - }, - .arena = decl_arena_state, - }, - }; - decl.analysis = .complete; - decl.generation = mod.generation; - - if (var_decl.extern_export_token) |maybe_export_token| { - if (token_tags[maybe_export_token] == .keyword_export) { - const export_src = decl.tokSrcLoc(maybe_export_token); - const name_token = var_decl.ast.mut_token + 1; - const name = tree.tokenSlice(name_token); // TODO identifierTokenString - // The scope needs to have the decl in it. - try mod.analyzeExport(&decl_scope.base, export_src, name, decl); - } - } - return type_changed; } -/// Call `deinit` on the result. -pub fn init(mod: *Module, decl: *Decl, arena: *Allocator) !AstGen { - var astgen: AstGen = .{ - .mod = mod, - .decl = decl, - .arena = arena, - }; - // Must be a block instruction at index 0 with the root body. - try astgen.instructions.append(mod.gpa, .{ - .tag = .block, - .data = .{ .pl_node = .{ - .src_node = 0, - .payload_index = undefined, - } }, - }); - return astgen; -} /// Asserts the scope is a child of a File and has an AST tree and returns the tree. pub fn tree(scope: *Scope) *const ast.Tree { switch (scope.tag) { @@ -1181,26 +706,6 @@ fn errorSetDecl( } -/// The string is stored in `arena` regardless of whether it uses @"" syntax. -pub fn identifierTokenStringTreeArena( - astgen: *AstGen, - token: ast.TokenIndex, - tree: *const ast.Tree, - arena: *Allocator, -) InnerError![]u8 { - const token_tags = tree.tokens.items(.tag); - assert(token_tags[token] == .identifier); - const ident_name = tree.tokenSlice(token); - if (!mem.startsWith(u8, ident_name, "@")) { - return arena.dupe(u8, ident_name); - } - var buf: ArrayListUnmanaged(u8) = .{}; - defer buf.deinit(astgen.gpa); - try astgen.parseStrLit(token, &buf, ident_name, 1); - return arena.dupe(u8, buf.items); -} - - if (mod.lookupIdentifier(scope, ident_name)) |decl| { const msg = msg: { @@ -1217,3 +722,54 @@ pub fn identifierTokenStringTreeArena( return mod.failWithOwnedErrorMsg(scope, msg); } + + var type_changed = true; + if (decl.typedValueManaged()) |tvm| { + type_changed = !tvm.typed_value.ty.eql(var_info.ty); + + tvm.deinit(mod.gpa); + } + + const new_variable = try decl_arena.allocator.create(Var); + new_variable.* = .{ + .owner_decl = decl, + .init = var_info.val orelse undefined, + .is_extern = is_extern, + .is_mutable = is_mutable, + .is_threadlocal = is_threadlocal, + }; + const var_val = try Value.Tag.variable.create(&decl_arena.allocator, new_variable); + + decl_arena_state.* = decl_arena.state; + decl.typed_value = .{ + .most_recent = .{ + .typed_value = .{ + .ty = var_info.ty, + .val = var_val, + }, + .arena = decl_arena_state, + }, + }; + decl.analysis = .complete; + decl.generation = mod.generation; + + + + if (is_mutable and !var_info.ty.isValidVarType(is_extern)) { + return mod.failTok( + &decl_scope.base, + var_decl.ast.mut_token, + "variable of type '{}' must be const", + .{var_info.ty}, + ); + } + + if (var_decl.extern_export_token) |maybe_export_token| { + if (token_tags[maybe_export_token] == .keyword_export) { + const export_src = decl.tokSrcLoc(maybe_export_token); + const name_token = var_decl.ast.mut_token + 1; + const name = tree.tokenSlice(name_token); // TODO identifierTokenString + // The scope needs to have the decl in it. + try mod.analyzeExport(&decl_scope.base, export_src, name, decl); + } + } diff --git a/src/AstGen.zig b/src/AstGen.zig index 3118d1fe94..cb1a28deda 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -1491,7 +1491,7 @@ fn varDecl( } if (var_decl.ast.init_node == 0) { - return astgen.failTok(name_token, "variables must be initialized", .{}); + return astgen.failNode(node, "variables must be initialized", .{}); } switch (token_tags[var_decl.ast.mut_token]) { @@ -1851,10 +1851,12 @@ fn fnDecl( const is_pub = fn_proto.visib_token != null; const is_export = blk: { - if (fn_proto.extern_export_token) |maybe_export_token| { - break :blk token_tags[maybe_export_token] == .keyword_export; - } - break :blk false; + const maybe_export_token = fn_proto.extern_export_token orelse break :blk false; + break :blk token_tags[maybe_export_token] == .keyword_export; + }; + const is_extern = blk: { + const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false; + break :blk token_tags[maybe_extern_token] == .keyword_extern; }; if (wip_decls.decl_index % 16 == 0 and wip_decls.decl_index != 0) { try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag); @@ -1937,11 +1939,6 @@ fn fnDecl( fn_proto.ast.return_type, ); - const is_extern = if (fn_proto.extern_export_token) |maybe_export_token| - token_tags[maybe_export_token] == .keyword_extern - else - false; - const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0) // TODO instead of enum literal type, this needs to be the // std.builtin.CallingConvention enum. We need to implement importing other files @@ -2070,10 +2067,94 @@ fn fnDecl( fn globalVarDecl( astgen: *AstGen, gz: *GenZir, + scope: *Scope, wip_decls: *WipDecls, + node: ast.Node.Index, var_decl: ast.full.VarDecl, ) InnerError!void { - @panic("TODO astgen globalVarDecl"); + const gpa = astgen.gpa; + const tree = &astgen.file.tree; + const token_tags = tree.tokens.items(.tag); + + const is_pub = var_decl.visib_token != null; + const is_export = blk: { + const maybe_export_token = var_decl.extern_export_token orelse break :blk false; + break :blk token_tags[maybe_export_token] == .keyword_export; + }; + const is_extern = blk: { + const maybe_extern_token = var_decl.extern_export_token orelse break :blk false; + break :blk token_tags[maybe_extern_token] == .keyword_extern; + }; + if (wip_decls.decl_index % 16 == 0 and wip_decls.decl_index != 0) { + try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag); + wip_decls.cur_bit_bag = 0; + } + wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> 2) | + (@as(u32, @boolToInt(is_pub)) << 30) | + (@as(u32, @boolToInt(is_export)) << 31); + wip_decls.decl_index += 1; + + const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var; + const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: { + if (!is_mutable) { + return astgen.failTok(tok, "threadlocal variable cannot be constant", .{}); + } + break :blk true; + } else false; + + const lib_name: u32 = if (var_decl.lib_name) |lib_name_token| blk: { + const lib_name_str = try gz.strLitAsString(lib_name_token); + break :blk lib_name_str.index; + } else 0; + + assert(var_decl.comptime_token == null); // handled by parser + if (var_decl.ast.align_node != 0) { + return astgen.failNode(var_decl.ast.align_node, "TODO implement alignment on globals", .{}); + } + if (var_decl.ast.section_node != 0) { + return astgen.failNode(var_decl.ast.section_node, "TODO linksection on globals", .{}); + } + + const var_inst: Zir.Inst.Ref = if (var_decl.ast.init_node != 0) vi: { + if (is_extern) { + return astgen.failNode( + var_decl.ast.init_node, + "extern variables have no initializers", + .{}, + ); + } + + const init_result_loc: AstGen.ResultLoc = if (var_decl.ast.type_node != 0) .{ + .ty = try expr(gz, scope, .{ .ty = .type_type }, var_decl.ast.type_node), + } else .none; + + const init_inst = try expr(gz, scope, init_result_loc, var_decl.ast.init_node); + + if (!is_mutable) { + // const globals are just their instruction. mutable globals have + // a special ZIR form. + break :vi init_inst; + } + + @panic("TODO astgen global variable"); + } else if (!is_extern) { + return astgen.failNode(node, "variables must be initialized", .{}); + } else if (var_decl.ast.type_node != 0) { + // Extern variable which has an explicit type. + + const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node); + + @panic("TODO AstGen extern global variable"); + } else { + return astgen.failNode(node, "unable to infer variable type", .{}); + }; + + const name_token = var_decl.ast.mut_token + 1; + const name_str_index = try gz.identAsString(name_token); + + try wip_decls.name_and_value.ensureCapacity(gpa, wip_decls.name_and_value.items.len + 2); + wip_decls.name_and_value.appendAssumeCapacity(name_str_index); + wip_decls.name_and_value.appendAssumeCapacity(@enumToInt(var_inst)); } fn comptimeDecl( @@ -2191,19 +2272,19 @@ fn structDeclInner( }, .global_var_decl => { - try astgen.globalVarDecl(gz, &wip_decls, tree.globalVarDecl(member_node)); + try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node)); continue; }, .local_var_decl => { - try astgen.globalVarDecl(gz, &wip_decls, tree.localVarDecl(member_node)); + try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node)); continue; }, .simple_var_decl => { - try astgen.globalVarDecl(gz, &wip_decls, tree.simpleVarDecl(member_node)); + try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node)); continue; }, .aligned_var_decl => { - try astgen.globalVarDecl(gz, &wip_decls, tree.alignedVarDecl(member_node)); + try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node)); continue; }, diff --git a/src/Module.zig b/src/Module.zig index bcb4b8dc99..2baa064255 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -2457,6 +2457,9 @@ fn freeExportList(gpa: *Allocator, export_list: []*Export) void { } pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node) !void { + const tracy = trace(@src()); + defer tracy.end(); + const comp = mod.comp; const gpa = mod.gpa; @@ -2468,7 +2471,9 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node // Determine whether we need to reload the file from disk and redo parsing and AstGen. switch (file.status) { - .never_loaded, .retryable_failure => {}, + .never_loaded, .retryable_failure => { + log.debug("first-time AstGen: {s}", .{file.sub_file_path}); + }, .parse_failure, .astgen_failure, .success => { const unchanged_metadata = stat.size == file.stat_size and