aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
AgeCommit message (Collapse)Author
2024-07-07Zcu: introduce `PerThread` and pass to all the functionsJacob Young
2024-07-04frontend: TrackedInst stores FileIndex instead of path digestAndrew Kelley
The purpose of using path digest was to reference a file in a serializable manner. Now that there is a stable index associated with files, it is a superior way to accomplish that goal, since removes one layer of indirection, and makes TrackedInst 8 bytes instead of 20. The saved Zig Compiler State file for "hello world" goes from 1.3M to 1.2M with this change.
2024-07-04Zcu: extract permanent state from FileAndrew Kelley
Primarily, this commit removes 2 fields from File, relying on the data being stored in the `files` field, with the key as the path digest, and the value as the struct decl corresponding to the File. This table is serialized into the compiler state that survives between incremental updates. Meanwhile, the File struct remains ephemeral data that can be reconstructed the first time it is needed by the compiler process, as well as operated on by independent worker threads. A key outcome of this commit is that there is now a stable index that can be used to refer to a File. This will be needed when serializing error messages to survive incremental compilation updates.
2024-07-04Sema: add missing referencesmlugg
2024-07-04compiler: rework type resolution, fully resolve all typesmlugg
I'm so sorry. This commit was just meant to be making all types fully resolve by queueing resolution at the moment of their creation. Unfortunately, a lot of dominoes ended up falling. Here's what happened: * I added a work queue job to fully resolve a type. * I realised that from here we could eliminate `Sema.types_to_resolve` if we made function codegen a separate job. This is desirable for simplicity of both spec and implementation. * This led to a new AIR traversal to detect whether any required type is unresolved. If a type in the AIR failed to resolve, then we can't run codegen. * Because full type resolution now occurs by the work queue job, a bug was exposed whereby error messages for type resolution were associated with the wrong `Decl`, resulting in duplicate error messages when the type was also resolved "by" its owner `Decl` (which really *all* resolution should be done on). * A correct fix for this requires using a different `Sema` when performing type resolution: we need a `Sema` owned by the type. Also note that this fix is necessary for incremental compilation. * This means a whole bunch of functions no longer need to take `Sema`s. * First-order effects: `resolveTypeFields`, `resolveTypeLayout`, etc * Second-order effects: `Type.abiAlignmentAdvanced`, `Value.orderAgainstZeroAdvanced`, etc The end result of this is, in short, a more correct compiler and a simpler language specification. This regressed a few error notes in the test cases, but nothing that seems worth blocking this change. Oh, also, I ripped out the old code in `test/src/Cases.zig` which introduced a dependency on `Compilation`. This dependency was problematic at best, and this code has been unused for a while. When we re-enable incremental test cases, we must rewrite their executor to use the compiler server protocol.
2024-07-04compiler: type.zig -> Type.zigmlugg
2024-07-04Zcu: store `LazySrcLoc` in error messagesmlugg
This change modifies `Zcu.ErrorMsg` to store a `Zcu.LazySrcLoc` rather than a `Zcu.SrcLoc`. Everything else is dominoes. The reason for this change is incremental compilation. If a failed `AnalUnit` is up-to-date on an update, we want to re-use the old error messages. However, the file containing the error location may have been modified, and `SrcLoc` cannot survive such a modification. `LazySrcLoc` is designed to be correct across incremental updates. Therefore, we defer source location resolution until `Compilation` gathers the compile errors into the `ErrorBundle`.
2024-07-04Zcu: rework reference tracesmlugg
Previously, `reference_table` mapped from a `Decl` being referenced to the `Decl` that performed the reference. This is convenient for constructing error messages, but problematic for incremental compilation. This is because on an incremental update, we want to efficiently remove all references triggered by an `AnalUnit` which is being re-analyzed. For this reason, `reference_table` now maps the other way: from the `AnalUnit` *performing* the reference, to the `AnalUnit` whose analysis was triggered. As a general rule, any call to any of the following functions should be preceded by a call to `Sema.addReferenceEntry`: * `Zcu.ensureDeclAnalyzed` * `Sema.ensureDeclAnalyzed` * `Zcu.ensureFuncBodyAnalyzed` * `Zcu.ensureFuncBodyAnalysisQueued` This is not just important for error messages, but also more fundamentally for incremental compilation. When an incremental update occurs, we must determine whether any `AnalUnit` has become unreferenced: in this case, we should ignore its associated error messages, and perhaps even remove it from the binary. For this reason, we no longer store only one reference to every `AnalUnit`, but every reference. At the end of an update, `Zcu.resolveReferences` will construct the reverse mapping, and as such identify which `AnalUnit`s are still referenced. The current implementation doesn't quite do what we need for incremental compilation here, but the framework is in place. Note that `Zcu.resolveReferences` does constitute a non-trivial amount of work on every incremental update. However, for incremental compilation, this work -- which will effectively be a graph traversal over all `AnalUnit` references -- seems strictly necessary. At the moment, this work is only done if the `Zcu` has any errors, when collecting them into the final `ErrorBundle`. An unsolved problem here is how to represent inline function calls in the reference trace. If `foo` performs an inline call to `bar` which references `qux`, then ideally, `bar` would be shown on the reference trace between `foo` and `qux`, but this is not currently the case. The solution here is probably for `Zcu.Reference` to store information about the source locations of active inline calls betweeen the referencer and its reference.
2024-07-04Zcu: key compile errors on `AnalUnit` where appropriatemlugg
This change seeks to more appropriately model the way semantic analysis works by drawing a more clear line between errors emitted by analyzing a `Decl` (in future a `Cau`) and errors emitted by analyzing a runtime function. This does change a few compile errors surrounding compile logs by adding more "also here" notes. The new notes are more technically correct, but perhaps not so helpful. They're not doing enough harm for me to put extensive thought into this for now.
2024-07-04Zcu: rework exportsmlugg
This commit reworks our representation of exported Decls and values in Zcu to be memory-optimized and trivially serialized. All exports are now stored in the `all_exports` array on `Zcu`. An `AnalUnit` which performs an export (either through an `export` annotation or by containing an analyzed `@export`) gains an entry into `single_exports` if it performs only one export, or `multi_exports` if it performs multiple. We no longer store a persistent mapping from a `Decl`/value to all exports of that entity; this state is not necessary for the majority of the pipeline. Instead, we construct it in `Zcu.processExports`, just before flush. This does not affect the algorithmic complexity of `processExports`, since this function already iterates all exports in the `Zcu`. The elimination of `decl_exports` and `value_exports` led to a few non-trivial backend changes. The LLVM backend has been wrangled into a more reasonable state in general regarding exports and externs. The C backend is currently disabled in this commit, because its support for `export` was quite broken, and that was exposed by this work -- I'm hoping @jacobly0 will be able to pick this up!
2024-07-04compiler: rename AnalSubject to AnalUnitmlugg
I meant to call it this originally, I just got mixed up -- sorry!
2024-06-26InternPool: rename `Depender` to `AnalSubject`mlugg
This is essentially just a rename. I also changed the representation of `AnalSubject` to use a `packed struct` rather than a non-exhaustive enum, but that change is relatively trivial.
2024-06-26Zir: make `src_line` absolute for `declaration` instructionsmlugg
We need special logic for updating line numbers anyway, so it's fine to just use absolute numbers here. This eliminates a field from `Decl`.
2024-06-22rename src/Module.zig to src/Zcu.zigAndrew Kelley
This patch is a pure rename plus only changing the file path in `@import` sites, so it is expected to not create version control conflicts, even when rebasing.
2024-06-20Merge pull request #20299 from mlugg/the-great-decl-splitMatthew Lugg
The Great Decl Split (preliminary work): refactor source locations and eliminate `Sema.Block.src_decl`.
2024-06-20Sema: fix performance regressionmlugg
LLVM fails to notice that in release builds, `logFn` ignores its arguments, so their computation can be elided. So, LLVM fails to elide this hashmap lookup. Its cost isn't too significant, but doing it in the hottest loop in Sema adds up! Technically, we could do the lookup a single time, before the loop, but it was cleanest (and a little faster) to just disable this log call at comptime when debug logging is disabled.
2024-06-18Zir: provide absolute node for `reify`mlugg
Since we track `reify` instructions across incremental updates, it is acceptable to treat it as the baseline for a relative source location. This turns out to be a good idea, since it makes it easy to define the source location for a reified type.
2024-06-17Sema: fix callconv detection in generic functionsmlugg
When analyzing `zirFunc` to instantiate a generic function, `sema.owner_decl` is not the owner Decl of the generic instance, but instead of the call site, so that dependencies are propagated correctly. (This aligns with the fact that in future, generic instantiations will not have a corresponding `Cau`.) So, when deciding the callconv in this case, we must check `sema.generic_owner` to determine whether the function is exported.
2024-06-16spirv: add support for workItemId, workGroupId, workGroupSizeRobin Voetter
2024-06-15Sema: eliminate Block.src_declmlugg
🦀 src_decl is gone 🦀 This commit eliminates the `src_decl` field from `Sema.Block`. This change goes further to eliminating unnecessary responsibilities of `Decl` in preparation for its major upcoming refactor. The two main remaining reponsibilities had to do with namespace types: `src_decl` was used to determine their line number and their name. The former use case is solved by storing the line number alongside type declarations (and reifications) in ZIR; this is actually more correct, since previously the line number assigned to the type was really the line number of the source declaration it was syntactically contained within, which does not necessarily line up. Consequently, this change makes debug info for namespace types more correct, although I am not sure how debuggers actually utilize this line number, if at all. Naming types was solved by a new field on `Block`, called `type_name_ctx`. In a sense, it represents the "namespace" we are currently within, including comptime function calls etc. We might want to revisit this in future, since the type naming rules seem to be a bit hand-wavey right now. As far as I can tell, there isn't any more preliminary work needed for me to start work on the behemoth task of splitting `Zcu.Decl` into the new `Nav` (Named Addressable Value) and `Cau` (Comptime Analysis Unit) types. This will be a sweeping change, impacting essentially every part of the pipeline after `AstGen`.
2024-06-15Zcu: rework source locationsmlugg
`LazySrcLoc` now stores a reference to the "base AST node" to which it is relative. The previous tagged union is `LazySrcLoc.Offset`. To make working with this structure convenient, `Sema.Block` contains a convenience `src` method which takes an `Offset` and returns a `LazySrcLoc`. The "base node" of a source location is no longer given by a `Decl`, but rather a `TrackedInst` representing either a `declaration`, `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl`. This is a more appropriate model, and removes an unnecessary responsibility from `Decl` in preparation for the upcoming refactor which will split it into `Nav` and `Cau`. As a part of these `Decl` reworks, the `src_node` field is eliminated. This change aids incremental compilation, and simplifies `Decl`. In some cases -- particularly in backends -- the source location of a declaration is desired. This was previously `Decl.srcLoc` and worked for any `Decl`. Now, it is `Decl.navSrcLoc` in reference to the upcoming refactor, since the set of `Decl`s this works for precisely corresponds to what will in future become a `Nav` -- that is, source-level declarations and generic function instantiations, but *not* type owner Decls. This commit introduces more tags to `LazySrcLoc.Offset` so as to eliminate the concept of `error.NeededSourceLocation`. Now, `.unneeded` should only be used to assert that an error path is unreachable. In the future, uses of `.unneeded` can probably be replaced with `undefined`. The `src_decl` field of `Sema.Block` no longer has a role in type resolution. Its main remaining purpose is to handle namespacing of type names. It will be eliminated entirely in a future commit to remove another undue responsibility from `Decl`. It is worth noting that in future, the `Zcu.SrcLoc` type should probably be eliminated entirely in favour of storing `Zcu.LazySrcLoc` values. This is because `Zcu.SrcLoc` is not valid across incremental updates, and we want to be able to reuse error messages from previous updates even if the source file in question changed. The error reporting logic should instead simply resolve the location from the `LazySrcLoc` on the fly.
2024-06-15compiler: move LazySrcLoc out of stdmlugg
This is in preparation for some upcoming changes to how we represent source locations in the compiler. The bulk of the change here is dealing with the removal of `src()` methods from `Zir` types.
2024-06-15Zir: use absolute nodes for declarations and type declarationsmlugg
The justification for using relative source nodes in ZIR is that it allows source locations -- which may be serialized across incremental updates -- to be relative to the source location of their containing declaration. However, having those "baseline" instructions themselves be relative to their own parent is counterproductive, since the source location updating problem is only being moved to `Decl`. Storing the absolute node here instead makes more sense, since it allows for this source location update logic to be elided entirely in the future by storing a `TrackedInst.Index` to resolve a source location relative to rather than a `Decl.Index`.
2024-06-10Zir: remove legacy `error_set_decl` variantsmlugg
These instructions are not emitted by AstGen. They also would have no effect even if they did appear in ZIR: the Sema handling for these instructions creates a Decl which the name strategy is applied to, and proceeds to never use it. This pointless CPU heater is now gone, saving 2 ZIR tags in the process.
2024-06-02Sema: validate function signature for Signal calling conventionVeikka Tuominen
2024-06-02Sema: add missing error for runtime `@ptrFromInt` to comptime-only typeVeikka Tuominen
Closes #20083
2024-05-22Revert "implement `@expect` builtin (#19658)"Andrew Kelley
This reverts commit a7de02e05216db9a04e438703ddf1b6b12f3fbef. This did not implement the accepted proposal, and I did not sign off on the changes. I would like a chance to review this, please.
2024-05-22implement `@expect` builtin (#19658)David Rubin
* implement `@expect` * add docs * add a second arg for expected bool * fix typo * move `expect` to use BinOp * update to newer langref format
2024-05-22llvm: fix `@wasmMemory{Size,Grow}` for wasm64Veikka Tuominen
Closes #19942
2024-05-22Sema: add missing declared here notewooster0
2024-05-14Sema: suggest using try/catch/if on method call on error unionWooster
2024-05-14Sema: improve error set/union discard/ignore errorsr00ster91
Previously the error had a note suggesting to use `try`, `catch`, or `if`, even for error sets where none of those work. Instead, in case of an error set the way you can handle the error depends very much on the specific case. For example you might be in a `catch` where you are discarding or ignoring the error set capture value, in which case one way to handle the error might be to `return` the error. So, in that case, we do not attach that error note. Additionally, this makes the error tell you what kind of an error it is: is it an error set or an error union? This distinction is very relevant in how to handle the error.
2024-05-14Sema: add error note for !?Type types when optional type is expectedr00ster91
2024-05-14Sema: remove periods from the few error messages that have themr00ster91
For consistency.
2024-05-14Sema error: talk about discarding instead of suppressingr00ster91
Maybe I'm just being pedantic here (most likely) but I don't like how we're just telling the user here how to "suppress this error" by "assigning the value to '_'". I think it's better if we use the word "discard" here which I think is the official terminology and also tells the user what it actually means to "assign the value to '_'". Also, using the value would also be a way to "suppress the error". It is just one of the two options: discard or use.
2024-05-11riscv: implement a basic `@intCast`David Rubin
the truncation panic logic is generated in Sema, so I don't need to roll anything of my own. I add all of the boilerplate for that detecting the truncation and it works in basic test cases!
2024-05-04InternPool: eliminate `var_args_param_type`mlugg
This was a "fake" type used to handle C varargs parameters, much like generic poison. In fact, it is treated identically to generic poison in all cases other than one (the final coercion of a call argument), which is trivially special-cased. Thus, it makes sense to remove this special tag and instead use `generic_poison_type` in its place. This fixes several bugs in Sema related to missing handling of this tag. Resolves: #19781
2024-05-02Sema: Don't generate runtime instructions on zirSplat if dest_ty doesn't ↵Antonio Gomes
have runtime bits
2024-04-28Sema+llvm: properly implement `Interrupt` callconvJulian
Co-authored-by: Veikka Tuominen <git@vexu.eu>
2024-04-23error on `undefined` end indexDavid Rubin
2024-04-22x86_64: fix C abi for unionsJacob Young
Closes #19721
2024-04-17Sema: cap depth of value printing in type namesmlugg
Certain types (notably, `std.ComptimeStringMap`) were resulting in excessively long type names when instantiated, which in turn resulted in excessively long symbol names. These are problematic for two reasons: * Symbol names are sometimes read by humans -- they ought to be readable. * Some other applications (looking at you, xcode) trip on very long symbol names. To work around this for now, we cap the depth of value printing at 1, as opposed to the normal 3. This doesn't guarantee anything -- there could still be, for instance, an incredibly long aggregate -- but it works around the issue in practice for the time being.
2024-04-18Sema: correctly make inferred allocs constantDavid Rubin
Resolves: #19677
2024-04-17compiler: rework comptime pointer representation and accessmlugg
We've got a big one here! This commit reworks how we represent pointers in the InternPool, and rewrites the logic for loading and storing from them at comptime. Firstly, the pointer representation. Previously, pointers were represented in a highly structured manner: pointers to fields, array elements, etc, were explicitly represented. This works well for simple cases, but is quite difficult to handle in the cases of unusual reinterpretations, pointer casts, offsets, etc. Therefore, pointers are now represented in a more "flat" manner. For types without well-defined layouts -- such as comptime-only types, automatic-layout aggregates, and so on -- we still use this "hierarchical" structure. However, for types with well-defined layouts, we use a byte offset associated with the pointer. This allows the comptime pointer access logic to deal with reinterpreted pointers far more gracefully, because the "base address" of a pointer -- for instance a `field` -- is a single value which pointer accesses cannot exceed since the parent has undefined layout. This strategy is also more useful to most backends -- see the updated logic in `codegen.zig` and `codegen/llvm.zig`. For backends which do prefer a chain of field and elements accesses for lowering pointer values, such as SPIR-V, there is a helpful function in `Value` which creates a strategy to derive a pointer value using ideally only field and element accesses. This is actually more correct than the previous logic, since it correctly handles pointer casts which, after the dust has settled, end up referring exactly to an aggregate field or array element. In terms of the pointer access code, it has been rewritten from the ground up. The old logic had become rather a mess of special cases being added whenever bugs were hit, and was still riddled with bugs. The new logic was written to handle the "difficult" cases correctly, the most notable of which is restructuring of a comptime-only array (for instance, converting a `[3][2]comptime_int` to a `[2][3]comptime_int`. Currently, the logic for loading and storing work somewhat differently, but a future change will likely improve the loading logic to bring it more in line with the store strategy. As far as I can tell, the rewrite has fixed all bugs exposed by #19414. As a part of this, the comptime bitcast logic has also been rewritten. Previously, bitcasts simply worked by serializing the entire value into an in-memory buffer, then deserializing it. This strategy has two key weaknesses: pointers, and undefined values. Representations of these values at comptime cannot be easily serialized/deserialized whilst preserving data, which means many bitcasts would become runtime-known if pointers were involved, or would turn `undefined` values into `0xAA`. The new logic works by "flattening" the datastructure to be cast into a sequence of bit-packed atomic values, and then "unflattening" it; using serialization when necessary, but with special handling for `undefined` values and for pointers which align in virtual memory. The resulting code is definitely slower -- more on this later -- but it is correct. The pointer access and bitcast logic required some helper functions and types which are not generally useful elsewhere, so I opted to split them into separate files `Sema/comptime_ptr_access.zig` and `Sema/bitcast.zig`, with simple re-exports in `Sema.zig` for their small public APIs. Whilst working on this branch, I caught various unrelated bugs with transitive Sema errors, and with the handling of `undefined` values. These bugs have been fixed, and corresponding behavior test added. In terms of performance, I do anticipate that this commit will regress performance somewhat, because the new pointer access and bitcast logic is necessarily more complex. I have not yet taken performance measurements, but will do shortly, and post the results in this PR. If the performance regression is severe, I will do work to to optimize the new logic before merge. Resolves: #19452 Resolves: #19460
2024-04-08InternPool: remove slice from byte aggregate keysJacob Young
This deletes a ton of lookups and avoids many UAF bugs. Closes #19485
2024-04-07Merge pull request #18988 from castholm/lazy-build-zigAndrew Kelley
std.Build: add `lazyImport` (`@import` for lazy dependencies)
2024-04-07Sema: support coercing ref to anonymous array init to many-pointerCarl Ã…stholm
2024-04-07Sema: fix runtime call of inline fn with comptime-known comptime-only ret typeCarl Ã…stholm
2024-04-06Sema: fix non-`pub` `usingnamespace` in `@typeInfo`Jacob Young
2024-04-02Sema: fix crash accessing array of opv typesJacob Young
Closes #19499