diff --git a/BRANCH_TODO b/BRANCH_TODO index 5e45a3d7da..aaf67be8f4 100644 --- a/BRANCH_TODO +++ b/BRANCH_TODO @@ -39,34 +39,6 @@ * AstGen: add result location pointers to function calls * nested function decl: how to refer to params? -pub fn createContainerDecl( - mod: *Module, - scope: *Scope, - base_token: std.zig.ast.TokenIndex, - decl_arena: *std.heap.ArenaAllocator, - typed_value: TypedValue, -) !*Decl { - const scope_decl = scope.ownerDecl().?; - const name = try mod.getAnonTypeName(scope, base_token); - defer mod.gpa.free(name); - const name_hash = scope.namespace().fullyQualifiedNameHash(name); - const src_hash: std.zig.SrcHash = undefined; - const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash); - const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State); - - decl_arena_state.* = decl_arena.state; - new_decl.typed_value = .{ - .most_recent = .{ - .typed_value = typed_value, - .arena = decl_arena_state, - }, - }; - new_decl.analysis = .complete; - new_decl.generation = mod.generation; - - return new_decl; -} - fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 { // TODO add namespaces, generic function signatrues const tree = scope.tree(); @@ -83,14 +55,6 @@ fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenInd } -pub fn analyzeFile(mod: *Module, file: *Scope.File) !void { - // We call `getAstTree` here so that `analyzeFile` has the error set that includes - // file system operations, but `analyzeNamespace` does not. - const tree = try mod.getAstTree(file.namespace.file_scope); - const decls = tree.rootDecls(); - return mod.analyzeNamespace(file.namespace, decls); -} - /// Returns `true` if the Decl type changed. /// Returns `true` if this is the first time analyzing the Decl. /// Returns `false` otherwise. @@ -143,29 +107,6 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa); defer analysis_arena.deinit(); - var code: Zir = blk: { - var astgen = try AstGen.init(mod, decl, &analysis_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 block_expr = node_datas[decl_node].lhs; - _ = try AstGen.comptimeExpr(&gen_scope, &gen_scope.base, .none, block_expr); - _ = try gen_scope.addBreak(.break_inline, 0, .void_value); - - const code = try gen_scope.finish(); - if (std.builtin.mode == .Debug and mod.comp.verbose_ir) { - code.dump(mod.gpa, "comptime_block", &gen_scope.base, 0) catch {}; - } - break :blk code; - }; - defer code.deinit(mod.gpa); - var sema: Sema = .{ .mod = mod, .gpa = mod.gpa, diff --git a/src/AstGen.zig b/src/AstGen.zig index e342ec1ac3..651d339a8f 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -78,6 +78,9 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir { }; defer astgen.deinit(gpa); + // String table indexes 0 and 1 are reserved for special meaning. + try astgen.string_bytes.appendSlice(gpa, &[_]u8{ 0, 0 }); + // We expect at least as many ZIR instructions and extra data items // as AST nodes. try astgen.instructions.ensureTotalCapacity(gpa, file.tree.nodes.len); @@ -3124,7 +3127,8 @@ fn testDecl( if (token_tags[str_lit_token] == .string_literal) { break :blk (try decl_block.strLitAsString(str_lit_token)).index; } - break :blk 0; + // String table index 1 has a special meaning here of test decl with no name. + break :blk 1; }; var fn_block: GenZir = .{ diff --git a/src/Module.zig b/src/Module.zig index 18c911f45e..55049ec547 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3415,7 +3415,7 @@ pub fn scanNamespace( const hash_u32s = zir.extra[extra_index..][0..4]; extra_index += 4; - const name_idx = zir.extra[extra_index]; + const decl_name_index = zir.extra[extra_index]; extra_index += 1; const decl_index = zir.extra[extra_index]; extra_index += 1; @@ -3429,7 +3429,6 @@ pub fn scanNamespace( extra_index += 1; break :inst inst; }; - const decl_name: ?[]const u8 = if (name_idx == 0) null else zir.nullTerminatedString(name_idx); const contents_hash = @bitCast(std.zig.SrcHash, hash_u32s.*); try mod.scanDecl( @@ -3437,7 +3436,7 @@ pub fn scanNamespace( &deleted_decls, &outdated_decls, contents_hash, - decl_name, + decl_name_index, decl_index, is_pub, is_exported, @@ -3477,7 +3476,7 @@ fn scanDecl( deleted_decls: *std.AutoArrayHashMap(*Decl, void), outdated_decls: *std.AutoArrayHashMap(*Decl, void), contents_hash: std.zig.SrcHash, - decl_name: ?[]const u8, + decl_name_index: u32, decl_index: Zir.Inst.Index, is_pub: bool, is_exported: bool, @@ -3493,6 +3492,11 @@ fn scanDecl( const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node; const decl_node = parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node); + const decl_name: ?[]const u8 = if (decl_name_index > 1) + zir.nullTerminatedString(decl_name_index) + else + null; + // We create a Decl for it regardless of analysis status. // Decls that have names are keyed in the namespace by the name. Decls without // names are keyed by their contents hash. This way we can detect if, for example, @@ -3510,8 +3514,14 @@ fn scanDecl( // Update the key reference to the longer-lived memory. gop.entry.key = &new_decl.contents_hash; gop.entry.value = new_decl; - // exported decls, comptime, test, and usingnamespace decls get analyzed. - if (decl_name == null or is_exported) { + // Exported decls, comptime decls, usingnamespace decls, and + // test decls if in test mode, get analyzed. + const want_analysis = is_exported or switch (decl_name_index) { + 0 => true, // comptime decl + 1 => mod.comp.bin_file.options.is_test, // test decl + else => false, + }; + if (want_analysis) { mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); } new_decl.is_pub = is_pub; diff --git a/src/Zir.zig b/src/Zir.zig index 9d388e77fd..4f18bf89d1 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -32,6 +32,7 @@ instructions: std.MultiArrayList(Inst).Slice, /// is referencing the data here whether they want to store both index and length, /// thus allowing null bytes, or store only index, and use null-termination. The /// `string_bytes` array is agnostic to either usage. +/// Indexes 0 and 1 are reserved for special cases. string_bytes: []u8, /// The meaning of this data is determined by `Inst.Tag` value. /// The first few indexes are reserved. See `ExtraIndex` for the values. @@ -2378,8 +2379,9 @@ pub const Inst = struct { /// 1. decl: { // for every decls_len /// src_hash: [4]u32, // hash of source bytes /// name: u32, // null terminated string index - /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls. - /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace + /// - 0 means comptime or usingnamespace decl. + /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace + /// - 1 means test decl with no name. /// value: Index, /// align: Ref, // if corresponding bit is set /// link_section: Ref, // if corresponding bit is set @@ -2411,8 +2413,9 @@ pub const Inst = struct { /// 1. decl: { // for every decls_len /// src_hash: [4]u32, // hash of source bytes /// name: u32, // null terminated string index - /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls. - /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace + /// - 0 means comptime or usingnamespace decl. + /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace + /// - 1 means test decl with no name. /// value: Index, /// align: Ref, // if corresponding bit is set /// link_section: Ref, // if corresponding bit is set @@ -2442,8 +2445,9 @@ pub const Inst = struct { /// 1. decl: { // for every decls_len /// src_hash: [4]u32, // hash of source bytes /// name: u32, // null terminated string index - /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls. - /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace + /// - 0 means comptime or usingnamespace decl. + /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace + /// - 1 means test decl with no name. /// value: Index, /// align: Ref, // if corresponding bit is set /// link_section: Ref, // if corresponding bit is set @@ -2483,8 +2487,9 @@ pub const Inst = struct { /// 1. decl: { // for every decls_len /// src_hash: [4]u32, // hash of source bytes /// name: u32, // null terminated string index - /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls. - /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace + /// - 0 means comptime or usingnamespace decl. + /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace + /// - 1 means test decl with no name. /// value: Index, /// - one of: block_inline, block_inline_var /// align: Ref, // if corresponding bit is set