authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-28 16:55:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-28 16:57:01-07:00
log3462193d30e54c17123cfe1e666d8e575d649426
tree2be792c1cdaf64b0df1f3923362346ddb89cbfc9
parentf86469bc5eea2b7bd95222d00a11bd287bfdfedf

stage2: prepare for mainining Decl references to ZIR indexes


4 files changed, 181 insertions(+), 120 deletions(-)

BRANCH_TODO-8
...@@ -426,14 +426,6 @@ pub fn analyzeNamespace(...@@ -426,14 +426,6 @@ pub fn analyzeNamespace(
426/// * C.FnBlock426/// * C.FnBlock
427/// * Wasm.FnData427/// * Wasm.FnData
428/// * SpirV.FnData428/// * SpirV.FnData
429 /// This name is relative to the containing namespace of the decl.
430 /// The memory is owned by the containing File ZIR.
431 pub fn getName(decl: Decl) ?[:0]const u8 {
432 const zir = decl.namespace.file_scope.zir;
433 const name_index = zir.extra[decl.zir_decl_index + 4];
434 if (name_index <= 1) return null;
435 return zir.nullTerminatedString(name_index);
436 }
437429
438430
439 extra_index += @boolToInt(has_align);431 extra_index += @boolToInt(has_align);
src/Module.zig+179-112
...@@ -154,13 +154,9 @@ pub const DeclPlusEmitH = struct {...@@ -154,13 +154,9 @@ pub const DeclPlusEmitH = struct {
154};154};
155155
156pub const Decl = struct {156pub const Decl = struct {
157 /// This name is relative to the containing namespace of the decl.157 /// For declarations that have corresponding source code, this is identical to
158 /// All Decls have names, even values that are not bound to a zig namespace.158 /// `getName().?`. For anonymous declarations this is allocated with Module's
159 /// This is necessary for mapping them to an address in the output file.159 /// allocator.
160 /// Memory is owned by this decl, using Module's allocator.
161 /// Note that this cannot be changed to reference ZIR memory because when
162 /// ZIR updates, it would change the Decl name, but we still need the previous
163 /// name to delete the Decl from the hash maps it has been inserted into.
164 name: [*:0]const u8,160 name: [*:0]const u8,
165 /// The most recent Type of the Decl after a successful semantic analysis.161 /// The most recent Type of the Decl after a successful semantic analysis.
166 /// Populated when `has_tv`.162 /// Populated when `has_tv`.
...@@ -186,10 +182,10 @@ pub const Decl = struct {...@@ -186,10 +182,10 @@ pub const Decl = struct {
186 /// The AST node index of this declaration.182 /// The AST node index of this declaration.
187 /// Must be recomputed when the corresponding source file is modified.183 /// Must be recomputed when the corresponding source file is modified.
188 src_node: ast.Node.Index,184 src_node: ast.Node.Index,
189 /// Index to ZIR `extra` array to the block of ZIR code that encodes the Decl expression.185 /// Index to ZIR `extra` array to the entry in the parent's decl structure
190 zir_block_index: Zir.Inst.Index,186 /// (the part that says "for every decls_len"). The first item at this index is
191 zir_align_ref: Zir.Inst.Ref = .none,187 /// the contents hash, followed by the name.
192 zir_linksection_ref: Zir.Inst.Ref = .none,188 zir_decl_index: Zir.Inst.Index,
193189
194 /// Represents the "shallow" analysis status. For example, for decls that are functions,190 /// Represents the "shallow" analysis status. For example, for decls that are functions,
195 /// the function type is analyzed with this set to `in_progress`, however, the semantic191 /// the function type is analyzed with this set to `in_progress`, however, the semantic
...@@ -234,6 +230,10 @@ pub const Decl = struct {...@@ -234,6 +230,10 @@ pub const Decl = struct {
234 is_pub: bool,230 is_pub: bool,
235 /// Whether the corresponding AST decl has a `export` keyword.231 /// Whether the corresponding AST decl has a `export` keyword.
236 is_exported: bool,232 is_exported: bool,
233 /// Whether the ZIR code provides an align instruction.
234 has_align: bool,
235 /// Whether the ZIR code provides a linksection instruction.
236 has_linksection: bool,
237237
238 /// Represents the position of the code in the output file.238 /// Represents the position of the code in the output file.
239 /// This is populated regardless of semantic analysis and code generation.239 /// This is populated regardless of semantic analysis and code generation.
...@@ -246,11 +246,6 @@ pub const Decl = struct {...@@ -246,11 +246,6 @@ pub const Decl = struct {
246 /// to save on memory usage.246 /// to save on memory usage.
247 fn_link: link.File.LinkFn,247 fn_link: link.File.LinkFn,
248248
249 /// This is stored separately in addition to being available via `zir_decl_index`
250 /// because when the underlying ZIR code is updated, this field is used to find
251 /// out if anything changed.
252 contents_hash: std.zig.SrcHash,
253
254 /// The shallow set of other decls whose typed_value could possibly change if this Decl's249 /// The shallow set of other decls whose typed_value could possibly change if this Decl's
255 /// typed_value is modified.250 /// typed_value is modified.
256 dependants: DepsTable = .{},251 dependants: DepsTable = .{},
...@@ -260,7 +255,13 @@ pub const Decl = struct {...@@ -260,7 +255,13 @@ pub const Decl = struct {
260255
261 /// The reason this is not `std.AutoArrayHashMapUnmanaged` is a workaround for256 /// The reason this is not `std.AutoArrayHashMapUnmanaged` is a workaround for
262 /// stage1 compiler giving me: `error: struct 'Module.Decl' depends on itself`257 /// stage1 compiler giving me: `error: struct 'Module.Decl' depends on itself`
263 pub const DepsTable = std.ArrayHashMapUnmanaged(*Decl, void, std.array_hash_map.getAutoHashFn(*Decl), std.array_hash_map.getAutoEqlFn(*Decl), false);258 pub const DepsTable = std.ArrayHashMapUnmanaged(
259 *Decl,
260 void,
261 std.array_hash_map.getAutoHashFn(*Decl),
262 std.array_hash_map.getAutoEqlFn(*Decl),
263 false,
264 );
264265
265 pub fn destroy(decl: *Decl, module: *Module) void {266 pub fn destroy(decl: *Decl, module: *Module) void {
266 const gpa = module.gpa;267 const gpa = module.gpa;
...@@ -283,6 +284,48 @@ pub const Decl = struct {...@@ -283,6 +284,48 @@ pub const Decl = struct {
283 }284 }
284 }285 }
285286
287 /// This name is relative to the containing namespace of the decl.
288 /// The memory is owned by the containing File ZIR.
289 pub fn getName(decl: Decl) ?[:0]const u8 {
290 const zir = decl.namespace.file_scope.zir;
291 return decl.getNameZir(zir);
292 }
293
294 pub fn getNameZir(decl: Decl, zir: Zir) ?[:0]const u8 {
295 const name_index = zir.extra[decl.zir_decl_index + 4];
296 if (name_index <= 1) return null;
297 return zir.nullTerminatedString(name_index);
298 }
299
300 pub fn contentsHash(decl: Decl) std.zig.SrcHash {
301 const zir = decl.namespace.file_scope.zir;
302 return decl.contentsHashZir(zir);
303 }
304
305 pub fn contentsHashZir(decl: Decl, zir: Zir) std.zig.SrcHash {
306 const hash_u32s = zir.extra[decl.zir_decl_index..][0..4];
307 const contents_hash = @bitCast(std.zig.SrcHash, hash_u32s.*);
308 return contents_hash;
309 }
310
311 pub fn zirBlockIndex(decl: Decl) Zir.Inst.Index {
312 const zir = decl.namespace.file_scope.zir;
313 return zir.extra[decl.zir_decl_index + 5];
314 }
315
316 pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref {
317 if (!decl.has_align) return .none;
318 const zir = decl.namespace.file_scope.zir;
319 return @intToEnum(Zir.Inst.Ref, zir.extra[decl.zir_decl_index + 6]);
320 }
321
322 pub fn zirLinkSectionRef(decl: Decl) Zir.Inst.Ref {
323 if (!decl.has_linksection) return .none;
324 const zir = decl.namespace.file_scope.zir;
325 const extra_index = decl.zir_decl_index + 6 + @boolToInt(decl.has_align);
326 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
327 }
328
286 pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index {329 pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index {
287 return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.src_node));330 return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.src_node));
288 }331 }
...@@ -653,9 +696,6 @@ pub const Scope = struct {...@@ -653,9 +696,6 @@ pub const Scope = struct {
653 /// TODO save memory with https://github.com/ziglang/zig/issues/8619.696 /// TODO save memory with https://github.com/ziglang/zig/issues/8619.
654 /// Does not contain anonymous decls.697 /// Does not contain anonymous decls.
655 decls: std.StringArrayHashMapUnmanaged(*Decl) = .{},698 decls: std.StringArrayHashMapUnmanaged(*Decl) = .{},
656 /// Names imported into the namespace via `usingnamespace`.
657 /// The key memory is owned by the ZIR of the `File` containing the `Namespace`.
658 usingnamespace_decls: std.StringArrayHashMapUnmanaged(*Namespace) = .{},
659699
660 pub fn deinit(ns: *Namespace, mod: *Module) void {700 pub fn deinit(ns: *Namespace, mod: *Module) void {
661 const gpa = mod.gpa;701 const gpa = mod.gpa;
...@@ -715,6 +755,11 @@ pub const Scope = struct {...@@ -715,6 +755,11 @@ pub const Scope = struct {
715 /// The namespace of the struct that represents this file.755 /// The namespace of the struct that represents this file.
716 /// Populated only when status is success.756 /// Populated only when status is success.
717 namespace: *Namespace,757 namespace: *Namespace,
758 /// All namespaces that this file contains. This is here so that
759 /// when a file is updated, and new ZIR code is generated, the
760 /// old and new ZIR code can be compared side by side and references
761 /// to old ZIR updated to new ZIR, and a changelist generated.
762 namespace_set: std.AutoArrayHashMapUnmanaged(*Namespace, void) = .{},
718763
719 pub fn unload(file: *File, gpa: *Allocator) void {764 pub fn unload(file: *File, gpa: *Allocator) void {
720 file.unloadTree(gpa);765 file.unloadTree(gpa);
...@@ -2919,17 +2964,15 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node...@@ -2919,17 +2964,15 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
2919 },2964 },
2920 };2965 };
29212966
2922 // Clear compile error for this file.2967 mod.lockAndClearFileCompileError(file);
2923 switch (file.status) {2968
2924 .success, .retryable_failure => {},2969 // Move previous ZIR to a local variable so we can compare it with the new one.
2925 .never_loaded, .parse_failure, .astgen_failure => {2970 var prev_zir = file.zir;
2926 const lock = comp.mutex.acquire();2971 const prev_zir_loaded = file.zir_loaded;
2927 defer lock.release();2972 file.zir_loaded = false;
2928 if (mod.failed_files.swapRemove(file)) |entry| {2973 file.zir = undefined;
2929 if (entry.value) |msg| msg.destroy(gpa); // Delete previous error message.2974 defer if (prev_zir_loaded) prev_zir.deinit(gpa);
2930 }2975
2931 },
2932 }
2933 file.unload(gpa);2976 file.unload(gpa);
29342977
2935 if (stat.size > std.math.maxInt(u32))2978 if (stat.size > std.math.maxInt(u32))
...@@ -3041,6 +3084,18 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node...@@ -3041,6 +3084,18 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
3041 });3084 });
3042 };3085 };
30433086
3087 if (prev_zir_loaded) {
3088 // Iterate over all Namespace objects contained within this File, looking at the
3089 // previous and new ZIR together and update the references to point
3090 // to the new one. For example, Decl name, Decl zir_decl_index, and Namespace
3091 // decl_table keys need to get updated to point to the new memory, even if the
3092 // underlying source code is unchanged.
3093 // We do not need to hold any locks at this time because all the Decl and Namespace
3094 // objects being touched are specific to this File, and the only other concurrent
3095 // tasks are touching other File objects.
3096 @panic("TODO implement update references from old ZIR to new ZIR");
3097 }
3098
3044 // TODO don't report compile errors until Sema @importFile3099 // TODO don't report compile errors until Sema @importFile
3045 if (file.zir.hasCompileErrors()) {3100 if (file.zir.hasCompileErrors()) {
3046 {3101 {
...@@ -3168,10 +3223,11 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -3168,10 +3223,11 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
3168 .deletion_flag = false,3223 .deletion_flag = false,
3169 .is_pub = true,3224 .is_pub = true,
3170 .is_exported = false,3225 .is_exported = false,
3226 .has_linksection = false,
3227 .has_align = false,
3171 .link = undefined, // don't try to codegen this3228 .link = undefined, // don't try to codegen this
3172 .fn_link = undefined, // not a function3229 .fn_link = undefined, // not a function
3173 .contents_hash = undefined, // top-level struct has no contents hash3230 .zir_decl_index = undefined,
3174 .zir_block_index = undefined,
31753231
3176 .has_tv = false,3232 .has_tv = false,
3177 .ty = undefined,3233 .ty = undefined,
...@@ -3263,15 +3319,16 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {...@@ -3263,15 +3319,16 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
3263 };3319 };
3264 defer block_scope.instructions.deinit(gpa);3320 defer block_scope.instructions.deinit(gpa);
32653321
3266 const inst_data = zir.instructions.items(.data)[decl.zir_block_index].pl_node;3322 const zir_block_index = decl.zirBlockIndex();
3323 const inst_data = zir.instructions.items(.data)[zir_block_index].pl_node;
3267 const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);3324 const extra = zir.extraData(Zir.Inst.Block, inst_data.payload_index);
3268 const body = zir.extra[extra.end..][0..extra.data.body_len];3325 const body = zir.extra[extra.end..][0..extra.data.body_len];
3269 const break_index = try sema.analyzeBody(&block_scope, body);3326 const break_index = try sema.analyzeBody(&block_scope, body);
32703327
3271 if (decl.zir_align_ref != .none) {3328 if (decl.zirAlignRef() != .none) {
3272 @panic("TODO implement decl align");3329 @panic("TODO implement decl align");
3273 }3330 }
3274 if (decl.zir_linksection_ref != .none) {3331 if (decl.zirLinkSectionRef() != .none) {
3275 @panic("TODO implement decl linksection");3332 @panic("TODO implement decl linksection");
3276 }3333 }
32773334
...@@ -3457,51 +3514,25 @@ pub fn scanNamespace(...@@ -3457,51 +3514,25 @@ pub fn scanNamespace(
3457 var bit_bag_index: usize = extra_start;3514 var bit_bag_index: usize = extra_start;
3458 var cur_bit_bag: u32 = undefined;3515 var cur_bit_bag: u32 = undefined;
3459 var decl_i: u32 = 0;3516 var decl_i: u32 = 0;
3517 var scan_decl_iter: ScanDeclIter = .{
3518 .module = mod,
3519 .namespace = namespace,
3520 .deleted_decls = &deleted_decls,
3521 .outdated_decls = &outdated_decls,
3522 .parent_decl = parent_decl,
3523 };
3460 while (decl_i < decls_len) : (decl_i += 1) {3524 while (decl_i < decls_len) : (decl_i += 1) {
3461 if (decl_i % 8 == 0) {3525 if (decl_i % 8 == 0) {
3462 cur_bit_bag = zir.extra[bit_bag_index];3526 cur_bit_bag = zir.extra[bit_bag_index];
3463 bit_bag_index += 1;3527 bit_bag_index += 1;
3464 }3528 }
3465 const is_pub = @truncate(u1, cur_bit_bag) != 0;3529 const flags = @truncate(u4, cur_bit_bag);
3466 cur_bit_bag >>= 1;3530 const decl_sub_index = extra_index;
3467 const is_exported = @truncate(u1, cur_bit_bag) != 0;3531 extra_index += 6;
3468 cur_bit_bag >>= 1;3532 extra_index += @truncate(u1, flags >> 2);
3469 const has_align = @truncate(u1, cur_bit_bag) != 0;3533 extra_index += @truncate(u1, flags >> 3);
3470 cur_bit_bag >>= 1;
3471 const has_section = @truncate(u1, cur_bit_bag) != 0;
3472 cur_bit_bag >>= 1;
3473
3474 const hash_u32s = zir.extra[extra_index..][0..4];
3475 extra_index += 4;
3476 const decl_name_index = zir.extra[extra_index];
3477 extra_index += 1;
3478 const decl_index = zir.extra[extra_index];
3479 extra_index += 1;
3480 const align_inst: Zir.Inst.Ref = if (!has_align) .none else inst: {
3481 const inst = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
3482 extra_index += 1;
3483 break :inst inst;
3484 };
3485 const section_inst: Zir.Inst.Ref = if (!has_section) .none else inst: {
3486 const inst = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
3487 extra_index += 1;
3488 break :inst inst;
3489 };
3490 const contents_hash = @bitCast(std.zig.SrcHash, hash_u32s.*);
34913534
3492 try mod.scanDecl(3535 try scanDecl(&scan_decl_iter, decl_sub_index, flags);
3493 namespace,
3494 &deleted_decls,
3495 &outdated_decls,
3496 contents_hash,
3497 decl_name_index,
3498 decl_index,
3499 is_pub,
3500 is_exported,
3501 align_inst,
3502 section_inst,
3503 parent_decl,
3504 );
3505 }3536 }
3506 // Handle explicitly deleted decls from the source code. This is one of two3537 // Handle explicitly deleted decls from the source code. This is one of two
3507 // places that Decl deletions happen. The other is in `Compilation`, after3538 // places that Decl deletions happen. The other is in `Compilation`, after
...@@ -3528,62 +3559,80 @@ pub fn scanNamespace(...@@ -3528,62 +3559,80 @@ pub fn scanNamespace(
3528 return extra_index;3559 return extra_index;
3529}3560}
35303561
3531fn scanDecl(3562const ScanDeclIter = struct {
3532 mod: *Module,3563 module: *Module,
3533 namespace: *Scope.Namespace,3564 namespace: *Scope.Namespace,
3534 deleted_decls: *std.AutoArrayHashMap(*Decl, void),3565 deleted_decls: *std.AutoArrayHashMap(*Decl, void),
3535 outdated_decls: *std.AutoArrayHashMap(*Decl, void),3566 outdated_decls: *std.AutoArrayHashMap(*Decl, void),
3536 contents_hash: std.zig.SrcHash,
3537 decl_name_index: u32,
3538 decl_index: Zir.Inst.Index,
3539 is_pub: bool,
3540 is_exported: bool,
3541 align_inst: Zir.Inst.Ref,
3542 section_inst: Zir.Inst.Ref,
3543 parent_decl: *Decl,3567 parent_decl: *Decl,
3544) InnerError!void {3568 usingnamespace_index: usize = 0,
3569 comptime_index: usize = 0,
3570 unnamed_test_index: usize = 0,
3571};
3572
3573fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!void {
3545 const tracy = trace(@src());3574 const tracy = trace(@src());
3546 defer tracy.end();3575 defer tracy.end();
35473576
3577 const mod = iter.module;
3578 const namespace = iter.namespace;
3548 const gpa = mod.gpa;3579 const gpa = mod.gpa;
3549 const zir = namespace.file_scope.zir;3580 const zir = namespace.file_scope.zir;
35503581
3551 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;3582 // zig fmt: off
3552 const decl_node = parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);3583 const is_pub = (flags & 0b0001) != 0;
3584 const is_exported = (flags & 0b0010) != 0;
3585 const has_align = (flags & 0b0100) != 0;
3586 const has_linksection = (flags & 0b1000) != 0;
3587 // zig fmt: on
35533588
3554 const decl_name: ?[]const u8 = if (decl_name_index > 1)3589 const decl_name_index = zir.extra[decl_sub_index + 4];
3555 zir.nullTerminatedString(decl_name_index)3590 const decl_index = zir.extra[decl_sub_index + 5];
3556 else3591 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;
3557 null;3592 const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
3593
3594 // Every Decl needs a name.
3595 const decl_name: [:0]const u8 = switch (decl_name_index) {
3596 0 => name: {
3597 if (is_exported) {
3598 const i = iter.usingnamespace_index;
3599 iter.usingnamespace_index += 1;
3600 break :name try std.fmt.allocPrintZ(gpa, "usingnamespace${d}", .{i});
3601 } else {
3602 const i = iter.comptime_index;
3603 iter.comptime_index += 1;
3604 break :name try std.fmt.allocPrintZ(gpa, "comptime${d}", .{i});
3605 }
3606 },
3607 1 => name: {
3608 const i = iter.unnamed_test_index;
3609 iter.unnamed_test_index += 1;
3610 break :name try std.fmt.allocPrintZ(gpa, "test${d}", .{i});
3611 },
3612 else => zir.nullTerminatedString(decl_name_index),
3613 };
35583614
3559 // We create a Decl for it regardless of analysis status.3615 // We create a Decl for it regardless of analysis status.
3560 // Decls that have names are keyed in the namespace by the name. Decls without3616 const gop = try namespace.decls.getOrPut(gpa, decl_name);
3561 // names are keyed by their contents hash. This way we can detect if, for example,
3562 // a comptime decl gets moved around in the file.
3563 const decl_key = decl_name orelse &contents_hash;
3564 const gop = try namespace.decls.getOrPut(gpa, decl_key);
3565 if (!gop.found_existing) {3617 if (!gop.found_existing) {
3566 const new_decl = try mod.allocateNewDecl(namespace, decl_node);3618 const new_decl = try mod.allocateNewDecl(namespace, decl_node);
3567 new_decl.contents_hash = contents_hash;3619 new_decl.name = decl_name;
3568 new_decl.name = try gpa.dupeZ(u8, decl_key);
3569 // Update the key reference to the longer-lived memory.
3570 gop.entry.key = &new_decl.contents_hash;
3571 gop.entry.value = new_decl;3620 gop.entry.value = new_decl;
3572 // Exported decls, comptime decls, usingnamespace decls, and3621 // Exported decls, comptime decls, usingnamespace decls, and
3573 // test decls if in test mode, get analyzed.3622 // test decls if in test mode, get analyzed.
3574 const want_analysis = is_exported or switch (decl_name_index) {3623 const want_analysis = is_exported or switch (decl_name_index) {
3575 0 => true, // comptime decl3624 0 => true, // comptime decl
3576 1 => mod.comp.bin_file.options.is_test, // test decl3625 1 => mod.comp.bin_file.options.is_test, // test decl
3577 else => false,3626 else => false, // TODO set to true for named tests when testing
3578 };3627 };
3579 if (want_analysis) {3628 if (want_analysis) {
3580 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });3629 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
3581 }3630 }
3582 new_decl.is_exported = is_exported;
3583 new_decl.is_pub = is_pub;3631 new_decl.is_pub = is_pub;
3584 new_decl.zir_block_index = decl_index;3632 new_decl.is_exported = is_exported;
3585 new_decl.zir_align_ref = align_inst;3633 new_decl.has_align = has_align;
3586 new_decl.zir_linksection_ref = section_inst;3634 new_decl.has_linksection = has_linksection;
3635 new_decl.zir_decl_index = @intCast(u32, decl_sub_index);
3587 return;3636 return;
3588 }3637 }
3589 const decl = gop.entry.value;3638 const decl = gop.entry.value;
...@@ -3591,12 +3640,13 @@ fn scanDecl(...@@ -3591,12 +3640,13 @@ fn scanDecl(
3591 // have been re-ordered.3640 // have been re-ordered.
3592 const prev_src_node = decl.src_node;3641 const prev_src_node = decl.src_node;
3593 decl.src_node = decl_node;3642 decl.src_node = decl_node;
3643
3594 decl.is_pub = is_pub;3644 decl.is_pub = is_pub;
3595 decl.is_exported = is_exported;3645 decl.is_exported = is_exported;
3596 decl.zir_block_index = decl_index;3646 decl.has_align = has_align;
3597 decl.zir_align_ref = align_inst;3647 decl.has_linksection = has_linksection;
3598 decl.zir_linksection_ref = section_inst;3648 decl.zir_decl_index = @intCast(u32, decl_sub_index);
3599 if (deleted_decls.swapRemove(decl) == null) {3649 if (iter.deleted_decls.swapRemove(decl) == null) {
3600 if (true) {3650 if (true) {
3601 @panic("TODO I think this code path is unreachable; should be caught by AstGen.");3651 @panic("TODO I think this code path is unreachable; should be caught by AstGen.");
3602 }3652 }
...@@ -3615,8 +3665,11 @@ fn scanDecl(...@@ -3615,8 +3665,11 @@ fn scanDecl(
3615 try mod.errNoteNonLazy(other_src_loc, msg, "previously declared here", .{});3665 try mod.errNoteNonLazy(other_src_loc, msg, "previously declared here", .{});
3616 try mod.failed_decls.putNoClobber(gpa, decl, msg);3666 try mod.failed_decls.putNoClobber(gpa, decl, msg);
3617 } else {3667 } else {
3668 if (true) {
3669 @panic("TODO reimplement scanDecl with regards to incremental compilation.");
3670 }
3618 if (!std.zig.srcHashEql(decl.contents_hash, contents_hash)) {3671 if (!std.zig.srcHashEql(decl.contents_hash, contents_hash)) {
3619 try outdated_decls.put(decl, {});3672 try iter.outdated_decls.put(decl, {});
3620 decl.contents_hash = contents_hash;3673 decl.contents_hash = contents_hash;
3621 } else if (try decl.isFunction()) switch (mod.comp.bin_file.tag) {3674 } else if (try decl.isFunction()) switch (mod.comp.bin_file.tag) {
3622 .coff => {3675 .coff => {
...@@ -3848,8 +3901,7 @@ fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node...@@ -3848,8 +3901,7 @@ fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node
3848 .linksection_val = undefined,3901 .linksection_val = undefined,
3849 .analysis = .unreferenced,3902 .analysis = .unreferenced,
3850 .deletion_flag = false,3903 .deletion_flag = false,
3851 .contents_hash = undefined,3904 .zir_decl_index = undefined,
3852 .zir_block_index = undefined,
3853 .link = switch (mod.comp.bin_file.tag) {3905 .link = switch (mod.comp.bin_file.tag) {
3854 .coff => .{ .coff = link.File.Coff.TextBlock.empty },3906 .coff => .{ .coff = link.File.Coff.TextBlock.empty },
3855 .elf => .{ .elf = link.File.Elf.TextBlock.empty },3907 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
...@@ -3869,6 +3921,8 @@ fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node...@@ -3869,6 +3921,8 @@ fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node
3869 .generation = 0,3921 .generation = 0,
3870 .is_pub = false,3922 .is_pub = false,
3871 .is_exported = false,3923 .is_exported = false,
3924 .has_linksection = false,
3925 .has_align = false,
3872 };3926 };
3873 return new_decl;3927 return new_decl;
3874}3928}
...@@ -4602,3 +4656,16 @@ pub fn getTarget(mod: Module) Target {...@@ -4602,3 +4656,16 @@ pub fn getTarget(mod: Module) Target {
4602pub fn optimizeMode(mod: Module) std.builtin.Mode {4656pub fn optimizeMode(mod: Module) std.builtin.Mode {
4603 return mod.comp.bin_file.options.optimize_mode;4657 return mod.comp.bin_file.options.optimize_mode;
4604}4658}
4659
4660fn lockAndClearFileCompileError(mod: *Module, file: *Scope.File) void {
4661 switch (file.status) {
4662 .success, .retryable_failure => {},
4663 .never_loaded, .parse_failure, .astgen_failure => {
4664 const lock = mod.comp.mutex.acquire();
4665 defer lock.release();
4666 if (mod.failed_files.swapRemove(file)) |entry| {
4667 if (entry.value) |msg| msg.destroy(mod.gpa); // Delete previous error message.
4668 }
4669 },
4670 }
4671}
src/link/C.zig+1
...@@ -79,6 +79,7 @@ pub fn deinit(self: *C) void {...@@ -79,6 +79,7 @@ pub fn deinit(self: *C) void {
79pub fn allocateDeclIndexes(self: *C, decl: *Module.Decl) !void {}79pub fn allocateDeclIndexes(self: *C, decl: *Module.Decl) !void {}
8080
81pub fn freeDecl(self: *C, decl: *Module.Decl) void {81pub fn freeDecl(self: *C, decl: *Module.Decl) void {
82 self.decl_table.removeAssertDiscard(decl);
82 decl.link.c.code.deinit(self.base.allocator);83 decl.link.c.code.deinit(self.base.allocator);
83 decl.fn_link.c.fwd_decl.deinit(self.base.allocator);84 decl.fn_link.c.fwd_decl.deinit(self.base.allocator);
84 var it = decl.fn_link.c.typedefs.iterator();85 var it = decl.fn_link.c.typedefs.iterator();
src/link/SpirV.zig+1
...@@ -127,6 +127,7 @@ pub fn updateDeclExports(...@@ -127,6 +127,7 @@ pub fn updateDeclExports(
127) !void {}127) !void {}
128128
129pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void {129pub fn freeDecl(self: *SpirV, decl: *Module.Decl) void {
130 self.decl_table.removeAssertDiscard(decl);
130 var fn_data = decl.fn_link.spirv;131 var fn_data = decl.fn_link.spirv;
131 fn_data.code.deinit(self.base.allocator);132 fn_data.code.deinit(self.base.allocator);
132 if (fn_data.id) |id| self.spirv_module.freeId(id);133 if (fn_data.id) |id| self.spirv_module.freeId(id);