| author | |
| committer | |
| log | fa6bb4b662155e4d6a61cc551b5d02a2a7d5d144 |
| tree | 23fb0d451b9aefa61c21cb7f1ffb40ec83dd57ef |
| parent | 2354cbafdb01d2a763b82cf03a72adef0794f187 |
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 | 39 | * AstGen: add result location pointers to function calls |
| 40 | 40 | * nested function decl: how to refer to params? |
| 41 | 41 | |
| 42 | pub 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 | ||
| 70 | 42 | fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenIndex) ![]u8 { |
| 71 | 43 | // TODO add namespaces, generic function signatrues |
| 72 | 44 | const tree = scope.tree(); |
| ... | ... | @@ -83,14 +55,6 @@ fn getAnonTypeName(mod: *Module, scope: *Scope, base_token: std.zig.ast.TokenInd |
| 83 | 55 | } |
| 84 | 56 | |
| 85 | 57 | |
| 86 | pub 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 | 58 | /// Returns `true` if the Decl type changed. |
| 95 | 59 | /// Returns `true` if this is the first time analyzing the Decl. |
| 96 | 60 | /// Returns `false` otherwise. |
| ... | ... | @@ -143,29 +107,6 @@ fn astgenAndSemaDecl(mod: *Module, decl: *Decl) !bool { |
| 143 | 107 | var analysis_arena = std.heap.ArenaAllocator.init(mod.gpa); |
| 144 | 108 | defer analysis_arena.deinit(); |
| 145 | 109 | |
| 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 | 110 | var sema: Sema = .{ |
| 170 | 111 | .mod = mod, |
| 171 | 112 | .gpa = mod.gpa, |
src/AstGen.zig+5-1| ... | ... | @@ -78,6 +78,9 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir { |
| 78 | 78 | }; |
| 79 | 79 | defer astgen.deinit(gpa); |
| 80 | 80 | |
| 81 | // String table indexes 0 and 1 are reserved for special meaning. | |
| 82 | try astgen.string_bytes.appendSlice(gpa, &[_]u8{ 0, 0 }); | |
| 83 | ||
| 81 | 84 | // We expect at least as many ZIR instructions and extra data items |
| 82 | 85 | // as AST nodes. |
| 83 | 86 | try astgen.instructions.ensureTotalCapacity(gpa, file.tree.nodes.len); |
| ... | ... | @@ -3124,7 +3127,8 @@ fn testDecl( |
| 3124 | 3127 | if (token_tags[str_lit_token] == .string_literal) { |
| 3125 | 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 | }; |
| 3129 | 3133 | |
| 3130 | 3134 | var fn_block: GenZir = .{ |
src/Module.zig+16-6| ... | ... | @@ -3415,7 +3415,7 @@ pub fn scanNamespace( |
| 3415 | 3415 | |
| 3416 | 3416 | const hash_u32s = zir.extra[extra_index..][0..4]; |
| 3417 | 3417 | extra_index += 4; |
| 3418 | const name_idx = zir.extra[extra_index]; | |
| 3418 | const decl_name_index = zir.extra[extra_index]; | |
| 3419 | 3419 | extra_index += 1; |
| 3420 | 3420 | const decl_index = zir.extra[extra_index]; |
| 3421 | 3421 | extra_index += 1; |
| ... | ... | @@ -3429,7 +3429,6 @@ pub fn scanNamespace( |
| 3429 | 3429 | extra_index += 1; |
| 3430 | 3430 | break :inst inst; |
| 3431 | 3431 | }; |
| 3432 | const decl_name: ?[]const u8 = if (name_idx == 0) null else zir.nullTerminatedString(name_idx); | |
| 3433 | 3432 | const contents_hash = @bitCast(std.zig.SrcHash, hash_u32s.*); |
| 3434 | 3433 | |
| 3435 | 3434 | try mod.scanDecl( |
| ... | ... | @@ -3437,7 +3436,7 @@ pub fn scanNamespace( |
| 3437 | 3436 | &deleted_decls, |
| 3438 | 3437 | &outdated_decls, |
| 3439 | 3438 | contents_hash, |
| 3440 | decl_name, | |
| 3439 | decl_name_index, | |
| 3441 | 3440 | decl_index, |
| 3442 | 3441 | is_pub, |
| 3443 | 3442 | is_exported, |
| ... | ... | @@ -3477,7 +3476,7 @@ fn scanDecl( |
| 3477 | 3476 | deleted_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3478 | 3477 | outdated_decls: *std.AutoArrayHashMap(*Decl, void), |
| 3479 | 3478 | contents_hash: std.zig.SrcHash, |
| 3480 | decl_name: ?[]const u8, | |
| 3479 | decl_name_index: u32, | |
| 3481 | 3480 | decl_index: Zir.Inst.Index, |
| 3482 | 3481 | is_pub: bool, |
| 3483 | 3482 | is_exported: bool, |
| ... | ... | @@ -3493,6 +3492,11 @@ fn scanDecl( |
| 3493 | 3492 | const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node; |
| 3494 | 3493 | const decl_node = parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node); |
| 3495 | 3494 | |
| 3495 | const decl_name: ?[]const u8 = if (decl_name_index > 1) | |
| 3496 | zir.nullTerminatedString(decl_name_index) | |
| 3497 | else | |
| 3498 | null; | |
| 3499 | ||
| 3496 | 3500 | // We create a Decl for it regardless of analysis status. |
| 3497 | 3501 | // Decls that have names are keyed in the namespace by the name. Decls without |
| 3498 | 3502 | // names are keyed by their contents hash. This way we can detect if, for example, |
| ... | ... | @@ -3510,8 +3514,14 @@ fn scanDecl( |
| 3510 | 3514 | // Update the key reference to the longer-lived memory. |
| 3511 | 3515 | gop.entry.key = &new_decl.contents_hash; |
| 3512 | 3516 | gop.entry.value = new_decl; |
| 3513 | // exported decls, comptime, test, and usingnamespace decls get analyzed. | |
| 3514 | if (decl_name == null or is_exported) { | |
| 3517 | // Exported decls, comptime decls, usingnamespace decls, and | |
| 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 | 3525 | mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl }); |
| 3516 | 3526 | } |
| 3517 | 3527 | new_decl.is_pub = is_pub; |
src/Zir.zig+13-8| ... | ... | @@ -32,6 +32,7 @@ instructions: std.MultiArrayList(Inst).Slice, |
| 32 | 32 | /// is referencing the data here whether they want to store both index and length, |
| 33 | 33 | /// thus allowing null bytes, or store only index, and use null-termination. The |
| 34 | 34 | /// `string_bytes` array is agnostic to either usage. |
| 35 | /// Indexes 0 and 1 are reserved for special cases. | |
| 35 | 36 | string_bytes: []u8, |
| 36 | 37 | /// The meaning of this data is determined by `Inst.Tag` value. |
| 37 | 38 | /// The first few indexes are reserved. See `ExtraIndex` for the values. |
| ... | ... | @@ -2378,8 +2379,9 @@ pub const Inst = struct { |
| 2378 | 2379 | /// 1. decl: { // for every decls_len |
| 2379 | 2380 | /// src_hash: [4]u32, // hash of source bytes |
| 2380 | 2381 | /// name: u32, // null terminated string index |
| 2381 | /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls. | |
| 2382 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | |
| 2382 | /// - 0 means comptime or usingnamespace decl. | |
| 2383 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | |
| 2384 | /// - 1 means test decl with no name. | |
| 2383 | 2385 | /// value: Index, |
| 2384 | 2386 | /// align: Ref, // if corresponding bit is set |
| 2385 | 2387 | /// link_section: Ref, // if corresponding bit is set |
| ... | ... | @@ -2411,8 +2413,9 @@ pub const Inst = struct { |
| 2411 | 2413 | /// 1. decl: { // for every decls_len |
| 2412 | 2414 | /// src_hash: [4]u32, // hash of source bytes |
| 2413 | 2415 | /// name: u32, // null terminated string index |
| 2414 | /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls. | |
| 2415 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | |
| 2416 | /// - 0 means comptime or usingnamespace decl. | |
| 2417 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | |
| 2418 | /// - 1 means test decl with no name. | |
| 2416 | 2419 | /// value: Index, |
| 2417 | 2420 | /// align: Ref, // if corresponding bit is set |
| 2418 | 2421 | /// link_section: Ref, // if corresponding bit is set |
| ... | ... | @@ -2442,8 +2445,9 @@ pub const Inst = struct { |
| 2442 | 2445 | /// 1. decl: { // for every decls_len |
| 2443 | 2446 | /// src_hash: [4]u32, // hash of source bytes |
| 2444 | 2447 | /// name: u32, // null terminated string index |
| 2445 | /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls. | |
| 2446 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | |
| 2448 | /// - 0 means comptime or usingnamespace decl. | |
| 2449 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | |
| 2450 | /// - 1 means test decl with no name. | |
| 2447 | 2451 | /// value: Index, |
| 2448 | 2452 | /// align: Ref, // if corresponding bit is set |
| 2449 | 2453 | /// link_section: Ref, // if corresponding bit is set |
| ... | ... | @@ -2483,8 +2487,9 @@ pub const Inst = struct { |
| 2483 | 2487 | /// 1. decl: { // for every decls_len |
| 2484 | 2488 | /// src_hash: [4]u32, // hash of source bytes |
| 2485 | 2489 | /// name: u32, // null terminated string index |
| 2486 | /// - can be 0 for test decls. always 0 for comptime and usingnamespace decls. | |
| 2487 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | |
| 2490 | /// - 0 means comptime or usingnamespace decl. | |
| 2491 | /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace | |
| 2492 | /// - 1 means test decl with no name. | |
| 2488 | 2493 | /// value: Index, |
| 2489 | 2494 | /// - one of: block_inline, block_inline_var |
| 2490 | 2495 | /// align: Ref, // if corresponding bit is set |