aboutsummaryrefslogtreecommitdiff
path: root/src/Zcu/PerThread.zig
AgeCommit message (Collapse)Author
2024-12-24compiler: remove Caumlugg
The `Cau` abstraction originated from noting that one of the two primary roles of the legacy `Decl` type was to be the subject of comptime semantic analysis. However, the data stored in `Cau` has always had some level of redundancy. While preparing for #131, I went to remove that redundany, and realised that `Cau` now had exactly one field: `owner`. This led me to conclude that `Cau` is, in fact, an unnecessary level of abstraction over what are in reality *fundamentally different* kinds of analysis unit (`AnalUnit`). Types, `Nav` vals, and `comptime` declarations are all analyzed in different ways, and trying to treat them as the same thing is counterproductive! So, these 3 cases are now different alternatives in `AnalUnit`. To avoid stealing bits from `InternPool`-based IDs, which are already a little starved for bits due to the sharding datastructures, `AnalUnit` is expanded to 64 bits (30 of which are currently unused). This doesn't impact memory usage too much by default, because we don't store `AnalUnit`s all too often; however, we do store them a lot under `-fincremental`, so a non-trivial bump to peak RSS can be observed there. This will be improved in the future when I made `InternPool.DepEntry` less memory-inefficient. `Zcu.PerThread.ensureCauAnalyzed` is split into 3 functions, for each of the 3 new types of `AnalUnit`. The new logic is much easier to understand, because it avoids conflating the logic of these fundamentally different cases.
2024-12-23Zir: refactor `declaration` instruction representationmlugg
The new representation is often more compact. It is also more straightforward to understand: for instance, `extern` is represented on the `declaration` instruction itself rather than using a special instruction. The same applies to `var`, making both of these far more compact. This commit also separates the type and value bodies of a `declaration` instruction. This is a prerequisite for #131. In general, `declaration` now directly encodes details of the syntax form used, and the embedded ZIR bodies are for actual expressions. The only exception to this is functions, where ZIR is effectively designed as if we had #1717. `extern fn` declarations are modeled as `extern const` with a function type, and normal `fn` definitions are modeled as `const` with a `func{,_fancy,_inferred}` instruction. This may change in the future, but improving on this was out of scope for this commit.
2024-12-20lldb: add pretty printer for intern pool indicesJacob Young
2024-12-19compiler: disallow `align` etc annotations on comptime-only globalsmlugg
This includes function aliases, but not function declarations. Also, re-introduce a target check for function alignment which was inadvertently removed in the prior commit.
2024-12-18compiler: disallow `callconv` etc from depending on function parametersmlugg
Resolves: #22261
2024-12-15compiler: remove doc comments from Zirmlugg
This code was left over from the legacy Autodoc implementation. No component of the compiler pipeline actually requires doc comments, so it is a waste of time and space to store them in ZIR.
2024-12-11std.Build.Cache.hit: work around macOS kernel bugAndrew Kelley
The previous commit cast doubt upon the initial report about macOS kernel behavior, identifying another reason that ENOENT could be returned from file creation. However, it is demonstrable that ENOENT can be returned for both cases: 1. create file race 2. handle refers to deleted directory This commit re-introduces the workaround for the file creation race on macOS however it does not unconditionally retry - it first tries again with O_EXCL to disambiguate the error condition that has occurred.
2024-12-10std.Build.Cache.hit: more discipline in error handlingAndrew Kelley
Previous commits 2b0929929d67e222ca6a9523a3a594ed456c4a51 4ea2f441df36cec61e1017f4d795d4037326c98c had this text: > There are no dir components, so you would think that this was > unreachable, however we have observed on macOS two processes racing to > do openat() with O_CREAT manifest in ENOENT. This appears to have been a misunderstanding based on the issue report #12138 and corresponding PR #12139 in which the steps to reproduce removed the cache directory in a loop which also executed detached Zig compiler processes. There is no evidence for the macOS kernel bug however the ENOENT is easily explained by the removal of the cache directory. This commit reverts those commits, ultimately reporting the ENOENT as an error rather than repeating the create file operation. However this commit also adds an explicit error set to `std.Build.Cache.hit` as well as changing the `failed_file_index` to a proper diagnostic field that fully communicates what failed, leading to more informative error messages on failure to check the cache. The equivalent failure when occuring for AstGen performs a fatal process kill, reasoning being that the compiler has an invariant of the cache directory not being yanked out from underneath it while executing. This could be made a more granular error in the future but I suspect such thing is not valuable to pursue. Related to #18340 but does not solve it.
2024-12-06Zcu: allow test declarations to be failedmlugg
The introduction of the `extended(astgen_error())` instruction allows a `test` declaration to be unresolved, i.e. the declaration doesn't even contain a `func`. I could modify AstGen to not do this, but it makes more sense to just handle this case when collecting test functions. Note that tests under incremental compilation are currently broken if you ever remove all references to a test; this is tracked as a subtask of #21165.
2024-12-05compiler: incremental compilation fixesmlugg
The previous commit exposed some bugs in incremental compilation. This commit fixes those, and adds a little more logging for debugging incremental compilation. Also, allow `ast-check -t` to dump ZIR when there are non-fatal AstGen errors.
2024-12-05compiler: allow files with AstGen errors to undergo semantic analysismlugg
This commit enhances AstGen to introduce a form of error resilience which allows valid ZIR to be emitted even when AstGen errors occur. When a non-fatal AstGen error (e.g. `appendErrorNode`) occurs, ZIR generation is not affected; the error is added to `astgen.errors` and ultimately to the errors stored in `extra`, but that doesn't stop us getting valid ZIR. Fatal AstGen errors (e.g. `failNode`) are a bit trickier. These errors return `error.AnalysisFail`, which is propagated up the stack. In theory, any parent expression can catch this error and handle it, continuing ZIR generation whilst throwing away whatever was lost. For now, we only do this in one place: when creating declarations. If a call to `fnDecl`, `comptimeDecl`, `globalVarDecl`, etc, returns `error.AnalysisFail`, the `declaration` instruction is still created, but its body simply contains the new `extended(astgen_error())` instruction, which instructs Sema to terminate semantic analysis with a transitive error. This means that a fatal AstGen error causes the innermost declaration containing the error to fail, but the rest of the file remains intact. If a source file contains parse errors, or an `error.AnalysisFail` happens when lowering the top-level struct (e.g. there is an error in one of its fields, or a name has multiple declarations), then lowering for the entire file fails. Alongside the existing `Zir.hasCompileErrors` query, this commit introduces `Zir.loweringFailed`, which returns `true` only in this case. The end result here is that files with AstGen failures will almost always still emit valid ZIR, and hence can undergo semantic analysis on the parts of the file which are (from AstGen's perspective) valid. This is a noteworthy improvement to UX, but the main motivation here is actually incremental compilation. Previously, AstGen failures caused lots of semantic analysis work to be thrown out, because all `AnalUnit`s in the file required re-analysis so as to trigger necessary transitive failures and remove stored compile errors which would no longer make sense (because a fresh compilation of this code would not emit those errors, as the units those errors applied to would fail sooner due to referencing a failed file). Now, this case only applies when a file has severe top-level errors, which is far less common than something like having an unused variable. Lastly, this commit changes a few errors in `AstGen` to become fatal when they were previously non-fatal and vice versa. If there is still a reasonable way to continue AstGen and lower to ZIR after an error, it is non-fatal; otherwise, it is fatal. For instance, `comptime const`, while redundant syntax, has a clear meaning we can lower; on the other hand, using an undeclared identifer has no sane lowering, so must trigger a fatal error.
2024-11-27std.os.windows: Map PIPE_NOT_AVAILABLE from OpenFile() to error.NoDevice ↵Justin Braben
(#21938)
2024-10-31compiler: remove anonymous struct types, unify all tuplesmlugg
This commit reworks how anonymous struct literals and tuples work. Previously, an untyped anonymous struct literal (e.g. `const x = .{ .a = 123 }`) was given an "anonymous struct type", which is a special kind of struct which coerces using structural equivalence. This mechanism was a holdover from before we used RLS / result types as the primary mechanism of type inference. This commit changes the language so that the type assigned here is a "normal" struct type. It uses a form of equivalence based on the AST node and the type's structure, much like a reified (`@Type`) type. Additionally, tuples have been simplified. The distinction between "simple" and "complex" tuple types is eliminated. All tuples, even those explicitly declared using `struct { ... }` syntax, use structural equivalence, and do not undergo staged type resolution. Tuples are very restricted: they cannot have non-`auto` layouts, cannot have aligned fields, and cannot have default values with the exception of `comptime` fields. Tuples currently do not have optimized layout, but this can be changed in the future. This change simplifies the language, and fixes some problematic coercions through pointers which led to unintuitive behavior. Resolves: #16865
2024-10-23combine codegen work queue and linker task queueAndrew Kelley
these tasks have some shared data dependencies so they cannot be done simultaneously. Future work should untangle these data dependencies so that more can be done in parallel. for now this commit ensures correctness by making linker input parsing and codegen tasks part of the same queue.
2024-10-23Merge pull request #21758 from kcbanner/dll_storage_classAndrew Kelley
Add `is_dll_import` to @extern, to support `__declspec(dllimport)` with the MSVC ABI
2024-10-22Add support for specifying `dll_storage_class` in @externkcbanner
2024-10-19compiler: introduce new `CallingConvention`mlugg
This commit begins implementing accepted proposal #21209 by making `std.builtin.CallingConvention` a tagged union. The stage1 dance here is a little convoluted. This commit introduces the new type as `NewCallingConvention`, keeping the old `CallingConvention` around. The compiler uses `std.builtin.NewCallingConvention` exclusively, but when fetching the type from `std` when running the compiler (e.g. with `getBuiltinType`), the name `CallingConvention` is used. This allows a prior build of Zig to be used to build this commit. The next commit will update `zig1.wasm`, and then the compiler and standard library can be updated to completely replace `CallingConvention` with `NewCallingConvention`. The second half of #21209 is to remove `@setAlignStack`, which will be implemented in another commit after updating `zig1.wasm`.
2024-10-16incremental: introduce `file` dependencies to handle AstGen failuresmlugg
The re-analysis here is a little coarse; it'd be nice in the future to have a way for an AstGen failure to preserve *all* analysis which depends on the last success, and just hide the compile errors which depend on it somehow. But I'm not sure how we'd achieve that, so this works fine for now. Resolves: #21223
2024-09-26I think it's better to put the imports at the topAndrew Kelley
2024-09-26fixes and make sema report errors when std.builtin wrongAndrew Kelley
instead of panicking
2024-09-26reimplement integer overflow safety panic function callsAndrew Kelley
in the llvm backend.
2024-09-26remove formatted panicsAndrew Kelley
implements #17969
2024-09-15compiler: always resolve field inits, remove unnecessary eager resolutionmlugg
Resolves: #21362
2024-09-12Replace deprecated default initializations with decl literalsLinus Groh
2024-09-09comp: `populateTestFunctions` shouldn't bubble up `AnalysisFail`David Rubin
`ensureCauAnalyzed` adds the anal_unit to the transitive failures, so we don't need to do anything here. The errors will be handled after this function.
2024-08-28std: update `std.builtin.Type` fields to follow naming conventionsmlugg
The compiler actually doesn't need any functional changes for this: Sema does reification based on the tag indices of `std.builtin.Type` already! So, no zig1.wasm update is necessary. This change is necessary to disallow name clashes between fields and decls on a type, which is a prerequisite of #9938.
2024-08-27Zcu: avoid trying to link failed container types and contained navsJacob Young
2024-08-27compiler: implement `@branchHint`, replacing `@setCold`mlugg
Implements the accepted proposal to introduce `@branchHint`. This builtin is permitted as the first statement of a block if that block is the direct body of any of the following: * a function (*not* a `test`) * either branch of an `if` * the RHS of a `catch` or `orelse` * a `switch` prong * an `or` or `and` expression It lowers to the ZIR instruction `extended(branch_hint(...))`. When Sema encounters this instruction, it sets `sema.branch_hint` appropriately, and `zirCondBr` etc are expected to reset this value as necessary. The state is on `Sema` rather than `Block` to make it automatically propagate up non-conditional blocks without special handling. If `@panic` is reached, the branch hint is set to `.cold` if none was already set; similarly, error branches get a hint of `.unlikely` if no hint is explicitly provided. If a condition is comptime-known, `cold` hints from the taken branch are allowed to propagate up, but other hints are discarded. This is because a `likely`/`unlikely` hint just indicates the direction this branch is likely to go, which is redundant information when the branch is known at comptime; but `cold` hints indicate that control flow is unlikely to ever reach this branch, meaning if the branch is always taken from its parent, then the parent is also unlikely to ever be reached. This branch information is stored in AIR `cond_br` and `switch_br`. In addition, `try` and `try_ptr` instructions have variants `try_cold` and `try_ptr_cold` which indicate that the error case is cold (rather than just unlikely); this is reachable through e.g. `errdefer unreachable` or `errdefer @panic("")`. A new API `unwrapSwitch` is introduced to `Air` to make it more convenient to access `switch_br` instructions. In time, I plan to update all AIR instructions to be accessed via an `unwrap` method which returns a convenient tagged union a la `InternPool.indexToKey`. The LLVM backend lowers branch hints for conditional branches and switches as follows: * If any branch is marked `unpredictable`, the instruction is marked `!unpredictable`. * Any branch which is marked as `cold` gets a `llvm.assume(i1 true) [ "cold"() ]` call to mark the code path cold. * If any branch is marked `likely` or `unlikely`, branch weight metadata is attached with `!prof`. Likely branches get a weight of 2000, and unlikely branches a weight of 1. In `switch` statements, un-annotated branches get a weight of 1000 as a "middle ground" hint, since there could be likely *and* unlikely *and* un-annotated branches. For functions, a `cold` hint corresponds to the `cold` function attribute, and other hints are currently ignored -- as far as I can tell LLVM doesn't really have a way to lower them. (Ideally, we would want the branch hint given in the function to propagate to call sites.) The compiler and standard library do not yet use this new builtin. Resolves: #21148
2024-08-25fix up merge conflicts with masterDavid Rubin
2024-08-25remove `mod` aliases for ZcusDavid Rubin
2024-08-25sema: clean-up `{union,struct}FieldAlignment` and friendsDavid Rubin
My main gripes with this design were that it was incorrectly namespaced, the naming was inconsistent and a bit wrong (`fooAlign` vs `fooAlignment`). This commit moves all the logic from `PerThread.zig` to use the zcu + tid system that the previous couple commits introduce. I've organized and merged the functions to be a bit more specific to their own purpose. - `fieldAlignment` takes a struct or union type, an index, and a Zcu (or the Sema version which takes a Pt), and gives you the alignment of the field at the index. - `structFieldAlignment` takes the field type itself, and provides the logic to handle special cases, such as externs. A design goal I had in mind was to avoid using the word 'struct' in the function name, when it worked for things that aren't structs, such as unions.
2024-08-25sema: rework type resolution to use Zcu when possibleDavid Rubin
2024-08-24incremental: fix adding/removing aggregate fieldsmlugg
I don't recall why I put these checks here -- they aren't correct. We can freely recreate a type even if its fields have changed, because we are going to re-do all type resolution. The only conditions for recreations are (a) the ZIR index must not be lost and (b) the number of captures must be the same. These conditions are permissible because if either is violated, we can guarantee that analysis of a valid `zirStructDecl` (etc) will never reference this type (since the ZIR index has just been tracked, and the captures have just been created based on the ZIR). Adds a corresponding test case. Resolves: #21185
2024-08-20Dwarf: fix issues with inline call sitesJacob Young
2024-08-20Dwarf: emit info about inline call sitesJacob Young
2024-08-18Zir: add instructions to fetch std.builtin typesmlugg
This replaces the constant `Zir.Inst.Ref` tags (and the analagous tags in `Air.Inst.Ref`, `InternPool.Index`) referring to types in `std.builtin` with a ZIR instruction `extended(builtin_type(...))` which instructs Sema to fetch such a type, effectively as if it were a shorthand for the ZIR for `@import("std").builtin.xyz`. Previously, this was achieved through constant tags in `Ref`. The analagous `InternPool` indices began as `simple_type` values, and were later rewritten to the correct type information. This system was kind of brittle, and more importantly, isn't compatible with incremental compilation of std, since incremental compilation relies on the ability to recreate types at different indices when they change. Replacing the old system with this instruction slightly increases the size of ZIR, but it simplifies logic and allows incremental compilation to work correctly on the standard library. This shouldn't have a significant impact on ZIR size or compiler performance, but I will take measurements in the PR to confirm this.
2024-08-18frontend: handle incremental updates of replaced runtime functionsmlugg
2024-08-18frontend: removed resolved IES data for outdated functionsmlugg
Without this, incremental updates which would change inferred error sets fail, since they assume the IES is resolved and equals the old set, resulting in false positive compile errors when e.g. coercing to an IES.
2024-08-17compiler: add some doc commentsmlugg
2024-08-17frontend: incremental compilation progressmlugg
Another big commit, sorry! This commit makes all fixes necessary for incremental updates of the compiler itself (specifically, adding a breakpoint to `zirCompileLog`) to succeed, at least on the frontend. The biggest change here is a reform to how types are handled. It works like this: * When a type is first created in `zirStructDecl` etc, its namespace is scanned. If the type requires resolution, an `interned` dependency is declared for the containing `AnalUnit`. * `zirThis` also declared an `interned` dependency for its `AnalUnit` on the namespace's owner type. * If the type's namespace changes, the surrounding source declaration changes hash, so `zirStructDecl` etc will be hit again. We check whether the namespace has been scanned this generation, and re-scan it if not. * Namespace lookups also check whether the namespace in question requires a re-scan based on the generation. This is because there's no guarantee that the `zirStructDecl` is re-analyzed before the namespace lookup is re-analyzed. * If a type's structure (essentially its fields) change, then the type's `Cau` is considered outdated. When the type is re-analyzed due to being outdated, or the `zirStructDecl` is re-analyzed by being transitively outdated, or a corresponding `zirThis` is re-analyzed by being transitively outdated, the struct type is recreated at a new `InternPool` index. The namespace's owner is updated (but not re-scanned, since that is handled by the mechanisms above), and the old type, while remaining a valid `Index`, is removed from the map metadata so it will never be found by lookups. `zirStructDecl` and `zirThis` store an `interned` dependency on the *new* type.
2024-08-17InternPool: don't remove outdated typesmlugg
When a type becomes outdated, there will still be lingering references to the old index -- for instance, any declaration whose value was that type holds a reference to that index. These references may live for an arbitrarily long time in some cases. So, we can't just remove the type from the pool -- the old `Index` must remain valid! Instead, we want to preserve the old `Index`, but avoid it from ever appearing in lookups. (It's okay if analysis of something referencing the old `Index` does weird stuff -- such analysis are guaranteed by the incremental compilation model to always be unreferenced.) So, we use the new `InternPool.putKeyReplace` to replace the shard entry for this index with the newly-created index.
2024-08-17Zcu: panic on usingnamespace with -fincrementalmlugg
2024-08-17Zcu: typomlugg
We were accidentally over-reporting most `namespace_name` deps and *not* reporting some actually outdated ones!
2024-08-17frontend: yet more incremental workmlugg
2024-08-17frontend: incremental progressmlugg
This commit makes more progress towards incremental compilation, fixing some crashes in the frontend. Notably, it fixes the regressions introduced by #20964. It also cleans up the "outdated file root" mechanism, by virtue of deleting it: we now detect outdated file roots just after updating ZIR refs, and re-scan their namespaces.
2024-08-16Dwarf: rework self-hosted debug info from scratchJacob Young
This is in preparation for incremental and actually being able to debug executables built by the x86_64 backend.
2024-08-11frontend: give all container types namespacesmlugg
Eliding the namespace when a container type has no decls was an experiment in saving memory, but it ended up causing more trouble than it was worth in various places. So, take the small memory hit for reified types, and just give every container type a namespace.
2024-08-11compiler: split Decl into Nav and Caumlugg
The type `Zcu.Decl` in the compiler is problematic: over time it has gained many responsibilities. Every source declaration, container type, generic instantiation, and `@extern` has a `Decl`. The functions of these `Decl`s are in some cases entirely disjoint. After careful analysis, I determined that the two main responsibilities of `Decl` are as follows: * A `Decl` acts as the "subject" of semantic analysis at comptime. A single unit of analysis is either a runtime function body, or a `Decl`. It registers incremental dependencies, tracks analysis errors, etc. * A `Decl` acts as a "global variable": a pointer to it is consistent, and it may be lowered to a specific symbol by the codegen backend. This commit eliminates `Decl` and introduces new types to model these responsibilities: `Cau` (Comptime Analysis Unit) and `Nav` (Named Addressable Value). Every source declaration, and every container type requiring resolution (so *not* including `opaque`), has a `Cau`. For a source declaration, this `Cau` performs the resolution of its value. (When #131 is implemented, it is unsolved whether type and value resolution will share a `Cau` or have two distinct `Cau`s.) For a type, this `Cau` is the context in which type resolution occurs. Every non-`comptime` source declaration, every generic instantiation, and every distinct `extern` has a `Nav`. These are sent to codegen/link: the backends by definition do not care about `Cau`s. This commit has some minor technically-breaking changes surrounding `usingnamespace`. I don't think they'll impact anyone, since the changes are fixes around semantics which were previously inconsistent (the behavior changed depending on hashmap iteration order!). Aside from that, this changeset has no significant user-facing changes. Instead, it is an internal refactor which makes it easier to correctly model the responsibilities of different objects, particularly regarding incremental compilation. The performance impact should be negligible, but I will take measurements before merging this work into `master`. Co-authored-by: Jacob Young <jacobly0@users.noreply.github.com> Co-authored-by: Jakub Konka <kubkon@jakubkonka.com>
2024-07-19dev: introduce dev environments that enable compiler feature setsJacob Young
2024-07-17Merge pull request #20653 from mlugg/incremental-fixMatthew Lugg
Zcu: updateZirRefs typo