authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-26 21:34:40-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-28 16:57:01-07:00
logfa6bb4b662155e4d6a61cc551b5d02a2a7d5d144
tree23fb0d451b9aefa61c21cb7f1ffb40ec83dd57ef
parent2354cbafdb01d2a763b82cf03a72adef0794f187

Sema: do not analyze test decls when not in test mode

We do this by reserving string table indexes 0 and 1 in ZIR to be special. Decls now have 0 to mean comptime or usingnamespace, and 1 to mean an unnamed test decl.

4 files changed, 34 insertions(+), 74 deletions(-)

BRANCH_TODO-59
...@@ -39,34 +39,6 @@...@@ -39,34 +39,6 @@
39 * AstGen: add result location pointers to function calls39 * AstGen: add result location pointers to function calls
40 * nested function decl: how to refer to params?40 * nested function decl: how to refer to params?
4141
42pub fn createContainerDecl(
43 mod: *Module,
44 scope: *Scope,
45 base_token: std.zig.ast.TokenIndex,
46 decl_arena: *std.heap.ArenaAllocator,
47 typed_value: TypedValue,
48) !*Decl {
49 const scope_decl = scope.ownerDecl().?;
50 const name = try mod.getAnonTypeName(scope, base_token);
51 defer mod.gpa.free(name);
52 const name_hash = scope.namespace().fullyQualifiedNameHash(name);
53 const src_hash: std.zig.SrcHash = undefined;
54 const new_decl = try mod.createNewDecl(scope, name, scope_decl.src_node, name_hash, src_hash);
55 const decl_arena_state = try decl_arena.allocator.create(std.heap.ArenaAllocator.State);
56
57 decl_arena_state.* = decl_arena.state;
58 new_decl.typed_value = .{
59 .most_recent = .{
60 .typed_value = typed_value,
61 .arena = decl_arena_state,
62 },
63 };
64 new_decl.analysis = .complete;
65 new_decl.generation = mod.generation;
66
67 return new_decl;
68}
69
70fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 {42fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 {
71 // TODO add namespaces, generic function signatrues43 // TODO add namespaces, generic function signatrues
72 const tree = scope.tree();44 const tree = scope.tree();
...@@ -83,14 +55,6 @@ fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenInd...@@ -83,14 +55,6 @@ fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenInd
83}55}
8456
8557
86pub fn analyzeFile(mod: *Module, file: *Scope.File) !void {
87 // We call `getAstTree` here so that `analyzeFile` has the error set that includes
88 // file system operations, but `analyzeNamespace` does not.
89 const tree = try mod.getAstTree(file.namespace.file_scope);
90 const decls = tree.rootDecls();
91 return mod.analyzeNamespace(file.namespace, decls);
92}
93
94/// Returns `true` if the Decl type changed.58/// Returns `true` if the Decl type changed.
95/// Returns `true` if this is the first time analyzing the Decl.59/// Returns `true` if this is the first time analyzing the Decl.
96/// Returns `false` otherwise.60/// Returns `false` otherwise.
...@@ -143,29 +107,6 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {...@@ -143,29 +107,6 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool {
143 var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa);107 var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa);
144 defer analysis_arena.deinit();108 defer analysis_arena.deinit();
145109
146 var code: Zir = blk: {
147 var astgen = try AstGen.init(mod, decl, &analysis_arena.allocator);
148 defer astgen.deinit();
149
150 var gen_scope: Scope.GenZir = .{
151 .force_comptime = true,
152 .parent = &decl.namespace.base,
153 .astgen = &astgen,
154 };
155 defer gen_scope.instructions.deinit(mod.gpa);
156
157 const block_expr = node_datas[decl_node].lhs;
158 _ = try AstGen.comptimeExpr(&gen_scope, &gen_scope.base, .none, block_expr);
159 _ = try gen_scope.addBreak(.break_inline, 0, .void_value);
160
161 const code = try gen_scope.finish();
162 if (std.builtin.mode == .Debug and mod.comp.verbose_ir) {
163 code.dump(mod.gpa, "comptime_block", &gen_scope.base, 0) catch {};
164 }
165 break :blk code;
166 };
167 defer code.deinit(mod.gpa);
168
169 var sema: Sema = .{110 var sema: Sema = .{
170 .mod = mod,111 .mod = mod,
171 .gpa = mod.gpa,112 .gpa = mod.gpa,
src/AstGen.zig+5-1
...@@ -78,6 +78,9 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {...@@ -78,6 +78,9 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
78 };78 };
79 defer astgen.deinit(gpa);79 defer astgen.deinit(gpa);
8080
81 // String table indexes 0 and 1 are reserved for special meaning.
82 try astgen.string_bytes.appendSlice(gpa, &[_]u8{ 0, 0 });
83
81 // We expect at least as many ZIR instructions and extra data items84 // We expect at least as many ZIR instructions and extra data items
82 // as AST nodes.85 // as AST nodes.
83 try astgen.instructions.ensureTotalCapacity(gpa, file.tree.nodes.len);86 try astgen.instructions.ensureTotalCapacity(gpa, file.tree.nodes.len);
...@@ -3124,7 +3127,8 @@ fn testDecl(...@@ -3124,7 +3127,8 @@ fn testDecl(
3124 if (token_tags[str_lit_token] == .string_literal) {3127 if (token_tags[str_lit_token] == .string_literal) {
3125 break :blk (try decl_block.strLitAsString(str_lit_token)).index;3128 break :blk (try decl_block.strLitAsString(str_lit_token)).index;
3126 }3129 }
3127 break :blk 0;3130 // String table index 1 has a special meaning here of test decl with no name.
3131 break :blk 1;
3128 };3132 };
31293133
3130 var fn_block: GenZir = .{3134 var fn_block: GenZir = .{
src/Module.zig+16-6
...@@ -3415,7 +3415,7 @@ pub fn scanNamespace(...@@ -3415,7 +3415,7 @@ pub fn scanNamespace(
34153415
3416 const hash_u32s = zir.extra[extra_index..][0..4];3416 const hash_u32s = zir.extra[extra_index..][0..4];
3417 extra_index += 4;3417 extra_index += 4;
3418 const name_idx = zir.extra[extra_index];3418 const decl_name_index = zir.extra[extra_index];
3419 extra_index += 1;3419 extra_index += 1;
3420 const decl_index = zir.extra[extra_index];3420 const decl_index = zir.extra[extra_index];
3421 extra_index += 1;3421 extra_index += 1;
...@@ -3429,7 +3429,6 @@ pub fn scanNamespace(...@@ -3429,7 +3429,6 @@ pub fn scanNamespace(
3429 extra_index += 1;3429 extra_index += 1;
3430 break :inst inst;3430 break :inst inst;
3431 };3431 };
3432 const decl_name: ?[]const u8 = if (name_idx == 0) null else zir.nullTerminatedString(name_idx);
3433 const contents_hash = @bitCast(std.zig.SrcHash, hash_u32s.*);3432 const contents_hash = @bitCast(std.zig.SrcHash, hash_u32s.*);
34343433
3435 try mod.scanDecl(3434 try mod.scanDecl(
...@@ -3437,7 +3436,7 @@ pub fn scanNamespace(...@@ -3437,7 +3436,7 @@ pub fn scanNamespace(
3437 &deleted_decls,3436 &deleted_decls,
3438 &outdated_decls,3437 &outdated_decls,
3439 contents_hash,3438 contents_hash,
3440 decl_name,3439 decl_name_index,
3441 decl_index,3440 decl_index,
3442 is_pub,3441 is_pub,
3443 is_exported,3442 is_exported,
...@@ -3477,7 +3476,7 @@ fn scanDecl(...@@ -3477,7 +3476,7 @@ fn scanDecl(
3477 deleted_decls: *std.AutoArrayHashMap(*Decl, void),3476 deleted_decls: *std.AutoArrayHashMap(*Decl, void),
3478 outdated_decls: *std.AutoArrayHashMap(*Decl, void),3477 outdated_decls: *std.AutoArrayHashMap(*Decl, void),
3479 contents_hash: std.zig.SrcHash,3478 contents_hash: std.zig.SrcHash,
3480 decl_name: ?[]const u8,3479 decl_name_index: u32,
3481 decl_index: Zir.Inst.Index,3480 decl_index: Zir.Inst.Index,
3482 is_pub: bool,3481 is_pub: bool,
3483 is_exported: bool,3482 is_exported: bool,
...@@ -3493,6 +3492,11 @@ fn scanDecl(...@@ -3493,6 +3492,11 @@ fn scanDecl(
3493 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;3492 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;
3494 const decl_node = parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);3493 const decl_node = parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
34953494
3495 const decl_name: ?[]const u8 = if (decl_name_index > 1)
3496 zir.nullTerminatedString(decl_name_index)
3497 else
3498 null;
3499
3496 // We create a Decl for it regardless of analysis status.3500 // We create a Decl for it regardless of analysis status.
3497 // Decls that have names are keyed in the namespace by the name. Decls without3501 // Decls that have names are keyed in the namespace by the name. Decls without
3498 // names are keyed by their contents hash. This way we can detect if, for example,3502 // names are keyed by their contents hash. This way we can detect if, for example,
...@@ -3510,8 +3514,14 @@ fn scanDecl(...@@ -3510,8 +3514,14 @@ fn scanDecl(
3510 // Update the key reference to the longer-lived memory.3514 // Update the key reference to the longer-lived memory.
3511 gop.entry.key = &new_decl.contents_hash;3515 gop.entry.key = &new_decl.contents_hash;
3512 gop.entry.value = new_decl;3516 gop.entry.value = new_decl;
3513 // exported decls, comptime, test, and usingnamespace decls get analyzed.3517 // Exported decls, comptime decls, usingnamespace decls, and
3514 if (decl_name == null or is_exported) {3518 // test decls if in test mode, get analyzed.
3519 const want_analysis = is_exported or switch (decl_name_index) {
3520 0 => true, // comptime decl
3521 1 => mod.comp.bin_file.options.is_test, // test decl
3522 else => false,
3523 };
3524 if (want_analysis) {
3515 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });3525 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
3516 }3526 }
3517 new_decl.is_pub = is_pub;3527 new_decl.is_pub = is_pub;
src/Zir.zig+13-8
...@@ -32,6 +32,7 @@ instructions: std.MultiArrayList(Inst).Slice,...@@ -32,6 +32,7 @@ instructions: std.MultiArrayList(Inst).Slice,
32/// is referencing the data here whether they want to store both index and length,32/// is referencing the data here whether they want to store both index and length,
33/// thus allowing null bytes, or store only index, and use null-termination. The33/// thus allowing null bytes, or store only index, and use null-termination. The
34/// `string_bytes` array is agnostic to either usage.34/// `string_bytes` array is agnostic to either usage.
35/// Indexes 0 and 1 are reserved for special cases.
35string_bytes: []u8,36string_bytes: []u8,
36/// The meaning of this data is determined by `Inst.Tag` value.37/// The meaning of this data is determined by `Inst.Tag` value.
37/// The first few indexes are reserved. See `ExtraIndex` for the values.38/// The first few indexes are reserved. See `ExtraIndex` for the values.
...@@ -2378,8 +2379,9 @@ pub const Inst = struct {...@@ -2378,8 +2379,9 @@ pub const Inst = struct {
2378 /// 1. decl: { // for every decls_len2379 /// 1. decl: { // for every decls_len
2379 /// src_hash: [4]u32, // hash of source bytes2380 /// src_hash: [4]u32, // hash of source bytes
2380 /// name: u32, // null terminated string index2381 /// name: u32, // null terminated string index
2381 /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls.2382 /// - 0 means comptime or usingnamespace decl.
2382 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2383 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2384 /// - 1 means test decl with no name.
2383 /// value: Index,2385 /// value: Index,
2384 /// align: Ref, // if corresponding bit is set2386 /// align: Ref, // if corresponding bit is set
2385 /// link_section: Ref, // if corresponding bit is set2387 /// link_section: Ref, // if corresponding bit is set
...@@ -2411,8 +2413,9 @@ pub const Inst = struct {...@@ -2411,8 +2413,9 @@ pub const Inst = struct {
2411 /// 1. decl: { // for every decls_len2413 /// 1. decl: { // for every decls_len
2412 /// src_hash: [4]u32, // hash of source bytes2414 /// src_hash: [4]u32, // hash of source bytes
2413 /// name: u32, // null terminated string index2415 /// name: u32, // null terminated string index
2414 /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls.2416 /// - 0 means comptime or usingnamespace decl.
2415 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2417 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2418 /// - 1 means test decl with no name.
2416 /// value: Index,2419 /// value: Index,
2417 /// align: Ref, // if corresponding bit is set2420 /// align: Ref, // if corresponding bit is set
2418 /// link_section: Ref, // if corresponding bit is set2421 /// link_section: Ref, // if corresponding bit is set
...@@ -2442,8 +2445,9 @@ pub const Inst = struct {...@@ -2442,8 +2445,9 @@ pub const Inst = struct {
2442 /// 1. decl: { // for every decls_len2445 /// 1. decl: { // for every decls_len
2443 /// src_hash: [4]u32, // hash of source bytes2446 /// src_hash: [4]u32, // hash of source bytes
2444 /// name: u32, // null terminated string index2447 /// name: u32, // null terminated string index
2445 /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls.2448 /// - 0 means comptime or usingnamespace decl.
2446 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2449 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2450 /// - 1 means test decl with no name.
2447 /// value: Index,2451 /// value: Index,
2448 /// align: Ref, // if corresponding bit is set2452 /// align: Ref, // if corresponding bit is set
2449 /// link_section: Ref, // if corresponding bit is set2453 /// link_section: Ref, // if corresponding bit is set
...@@ -2483,8 +2487,9 @@ pub const Inst = struct {...@@ -2483,8 +2487,9 @@ pub const Inst = struct {
2483 /// 1. decl: { // for every decls_len2487 /// 1. decl: { // for every decls_len
2484 /// src_hash: [4]u32, // hash of source bytes2488 /// src_hash: [4]u32, // hash of source bytes
2485 /// name: u32, // null terminated string index2489 /// name: u32, // null terminated string index
2486 /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls.2490 /// - 0 means comptime or usingnamespace decl.
2487 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2491 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
2492 /// - 1 means test decl with no name.
2488 /// value: Index,2493 /// value: Index,
2489 /// - one of: block_inline, block_inline_var2494 /// - one of: block_inline, block_inline_var
2490 /// align: Ref, // if corresponding bit is set2495 /// align: Ref, // if corresponding bit is set