| ... | @@ -154,13 +154,9 @@ pub const DeclPlusEmitH = struct { | ... | @@ -154,13 +154,9 @@ pub const DeclPlusEmitH = struct { |
| 154 | }; | 154 | }; |
| 155 | | 155 | |
| 156 | pub const Decl = struct { | 156 | pub 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, |
| 193 | | 189 | |
| 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 semantic | 191 | /// 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, |
| 237 | | 237 | |
| 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, |
| 248 | | 248 | |
| 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's | 249 | /// 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 { |
| 260 | | 255 | |
| 261 | /// The reason this is not `std.AutoArrayHashMapUnmanaged` is a workaround for | 256 | /// 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 | ); |
| 264 | | 265 | |
| 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 | } |
| 285 | | 286 | |
| | 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) = .{}, | | |
| 659 | | 699 | |
| 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) = .{}, |
| 718 | | 763 | |
| 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 | }; |
| 2921 | | 2966 | |
| 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); |
| 2934 | | 2977 | |
| 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 | }; |
| 3043 | | 3086 | |
| | 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 @importFile | 3099 | // 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 this | 3228 | .link = undefined, // don't try to codegen this |
| 3172 | .fn_link = undefined, // not a function | 3229 | .fn_link = undefined, // not a function |
| 3173 | .contents_hash = undefined, // top-level struct has no contents hash | 3230 | .zir_decl_index = undefined, |
| 3174 | .zir_block_index = undefined, | | |
| 3175 | | 3231 | |
| 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); |
| 3265 | | 3321 | |
| 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); |
| 3270 | | 3327 | |
| 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 | } |
| 3277 | | 3334 | |
| ... | @@ -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.*); | | |
| 3491 | | 3534 | |
| 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 two | 3537 | // Handle explicitly deleted decls from the source code. This is one of two |
| 3507 | // places that Decl deletions happen. The other is in `Compilation`, after | 3538 | // 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 | } |
| 3530 | | 3561 | |
| 3531 | fn scanDecl( | 3562 | const 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 | |
| | 3573 | fn 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(); |
| 3547 | | 3576 | |
| | 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; |
| 3550 | | 3581 | |
| 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 |
| 3553 | | 3588 | |
| 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 | else | 3591 | 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 | }; |
| 3558 | | 3614 | |
| 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 without | 3616 | 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, and | 3621 | // 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 decl | 3624 | 0 => true, // comptime decl |
| 3576 | 1 => mod.comp.bin_file.options.is_test, // test decl | 3625 | 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 { |
| 4602 | pub fn optimizeMode(mod: Module) std.builtin.Mode { | 4656 | pub 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 | |
| | 4660 | fn 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 | } |