diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2024-12-05 18:03:09 +0000 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2024-12-05 19:58:42 +0000 |
| commit | 8f849684f46ad0835bd9591f420e49e212880cb2 (patch) | |
| tree | ebf5d639609a744108f4e9a356d0074c25a640d9 /src | |
| parent | 7f3211a101d8763ec5f0009b219f6819dba2cd35 (diff) | |
| download | zig-8f849684f46ad0835bd9591f420e49e212880cb2.tar.gz zig-8f849684f46ad0835bd9591f420e49e212880cb2.zip | |
std.zig.Zir: improve instruction tracking
The main change here is to partition tracked instructions found within a
declaration. It's very unlikely that, for instance, a `struct { ... }`
type declaration was intentionally turned into a reification or an
anonymous initialization, so it makes sense to track things in a few
different arrays.
In particular, this fixes an issue where a `func` instruction could
wrongly be mapped to something else if the types of function parameters
changed. This would cause huge problems further down the pipeline; we
expect that if a `declaration` is tracked, and it previously contained a
`func`/`func_inferred`/`func_fancy`, then this instruction is either
tracked to another `func`/`func_inferred`/`func_fancy` instruction, or
is lost.
Also, this commit takes the opportunity to rename the functions actually
doing this logic. `Zir.findDecls` was a name that might have made sense
at some point, but nowadays, it's definitely not finding declarations,
and it's not *exclusively* finding type declarations. Instead, the point
is to find instructions which we want to track; hence the new name,
`Zir.findTrackable`.
Lastly, a nice side effect of partitioning the output of `findTrackable`
is that `Zir.declIterator` no longer needs to accept input instructions
which aren't type declarations (e.g. `reify`, `func`).
Diffstat (limited to 'src')
| -rw-r--r-- | src/Zcu.zig | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/src/Zcu.zig b/src/Zcu.zig index d03eb4cc9a..bb2dc2a8df 100644 --- a/src/Zcu.zig +++ b/src/Zcu.zig @@ -2593,26 +2593,44 @@ pub fn mapOldZirToNew( defer match_stack.deinit(gpa); // Used as temporary buffers for namespace declaration instructions - var old_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .empty; - defer old_decls.deinit(gpa); - var new_decls: std.ArrayListUnmanaged(Zir.Inst.Index) = .empty; - defer new_decls.deinit(gpa); + var old_contents: Zir.DeclContents = .init; + defer old_contents.deinit(gpa); + var new_contents: Zir.DeclContents = .init; + defer new_contents.deinit(gpa); // Map the main struct inst (and anything in its fields) { - try old_zir.findDeclsRoot(gpa, &old_decls); - try new_zir.findDeclsRoot(gpa, &new_decls); + try old_zir.findTrackableRoot(gpa, &old_contents); + try new_zir.findTrackableRoot(gpa, &new_contents); - assert(old_decls.items[0] == .main_struct_inst); - assert(new_decls.items[0] == .main_struct_inst); + assert(old_contents.explicit_types.items[0] == .main_struct_inst); + assert(new_contents.explicit_types.items[0] == .main_struct_inst); - // We don't have any smart way of matching up these type declarations, so we always - // correlate them based on source order. - const n = @min(old_decls.items.len, new_decls.items.len); - try match_stack.ensureUnusedCapacity(gpa, n); - for (old_decls.items[0..n], new_decls.items[0..n]) |old_inst, new_inst| { + assert(old_contents.func_decl == null); + assert(new_contents.func_decl == null); + + // We don't have any smart way of matching up these instructions, so we correlate them based on source order + // in their respective arrays. + + const num_explicit_types = @min(old_contents.explicit_types.items.len, new_contents.explicit_types.items.len); + try match_stack.ensureUnusedCapacity(gpa, @intCast(num_explicit_types)); + for ( + old_contents.explicit_types.items[0..num_explicit_types], + new_contents.explicit_types.items[0..num_explicit_types], + ) |old_inst, new_inst| { + // Here we use `match_stack`, so that we will recursively consider declarations on these types. match_stack.appendAssumeCapacity(.{ .old_inst = old_inst, .new_inst = new_inst }); } + + const num_other = @min(old_contents.other.items.len, new_contents.other.items.len); + try inst_map.ensureUnusedCapacity(gpa, @intCast(num_other)); + for ( + old_contents.other.items[0..num_other], + new_contents.other.items[0..num_other], + ) |old_inst, new_inst| { + // These instructions don't have declarations, so we just modify `inst_map` directly. + inst_map.putAssumeCapacity(old_inst, new_inst); + } } while (match_stack.popOrNull()) |match_item| { @@ -2700,17 +2718,39 @@ pub fn mapOldZirToNew( // Match the `declaration` instruction try inst_map.put(gpa, old_decl_inst, new_decl_inst); - // Find container type declarations within this declaration - try old_zir.findDecls(gpa, &old_decls, old_decl_inst); - try new_zir.findDecls(gpa, &new_decls, new_decl_inst); + // Find trackable instructions within this declaration + try old_zir.findTrackable(gpa, &old_contents, old_decl_inst); + try new_zir.findTrackable(gpa, &new_contents, new_decl_inst); + + // We don't have any smart way of matching up these instructions, so we correlate them based on source order + // in their respective arrays. - // We don't have any smart way of matching up these type declarations, so we always - // correlate them based on source order. - const n = @min(old_decls.items.len, new_decls.items.len); - try match_stack.ensureUnusedCapacity(gpa, n); - for (old_decls.items[0..n], new_decls.items[0..n]) |old_inst, new_inst| { + const num_explicit_types = @min(old_contents.explicit_types.items.len, new_contents.explicit_types.items.len); + try match_stack.ensureUnusedCapacity(gpa, @intCast(num_explicit_types)); + for ( + old_contents.explicit_types.items[0..num_explicit_types], + new_contents.explicit_types.items[0..num_explicit_types], + ) |old_inst, new_inst| { + // Here we use `match_stack`, so that we will recursively consider declarations on these types. match_stack.appendAssumeCapacity(.{ .old_inst = old_inst, .new_inst = new_inst }); } + + const num_other = @min(old_contents.other.items.len, new_contents.other.items.len); + try inst_map.ensureUnusedCapacity(gpa, @intCast(num_other)); + for ( + old_contents.other.items[0..num_other], + new_contents.other.items[0..num_other], + ) |old_inst, new_inst| { + // These instructions don't have declarations, so we just modify `inst_map` directly. + inst_map.putAssumeCapacity(old_inst, new_inst); + } + + if (old_contents.func_decl) |old_func_inst| { + if (new_contents.func_decl) |new_func_inst| { + // There are no declarations on a function either, so again, we just directly add it to `inst_map`. + try inst_map.put(gpa, old_func_inst, new_func_inst); + } + } } } } |
