Commit Graph

2446 Commits

Author SHA1 Message Date
Andrew Kelley
dd75e7bcb1 Sema: add missing error and test for bool not on vector of ints 2025-06-13 05:59:25 -04:00
Andrew Kelley
dcdb4422b8 Merge pull request #24124 from mlugg/better-backend-pipeline-2
compiler: threaded codegen (and more goodies)
2025-06-12 20:46:36 -04:00
Daniel Kongsgaard
5e3c0b7af7 Allow more operators on bool vectors (#24131)
* Sema: allow binary operations and boolean not on vectors of bool

* langref: Clarify use of operators on vectors (`and` and `or` not allowed)

closes #24093
2025-06-12 15:16:23 -07:00
mlugg
71baa5e769 compiler: improve progress output
Update the estimated total items for the codegen and link progress nodes
earlier. Rather than waiting for the main thread to dispatch the tasks,
we can add the item to the estimated total as soon as we queue the main
task. The only difference is we need to complete it even in error cases.
2025-06-12 17:51:31 +01:00
Jacob Young
746137034e Sema: fix union layout logic to match struct layout logic 2025-06-12 17:51:30 +01:00
Jacob Young
c95b1bf2d3 x86_64: remove air references from mir 2025-06-12 13:55:41 +01:00
mlugg
c4ec382fc8 InternPool: store the Nav types are named after
When the name strategy is `.parent`, the DWARF info really wants to know
what `Nav` we were named after to emit a more optimal hierarchy.
2025-06-12 13:55:41 +01:00
mlugg
424e6ac54b compiler: minor refactors to ZCU linking
* The `codegen_nav`, `codegen_func`, `codegen_type` tasks are renamed to
  `link_nav`, `link_func`, and `link_type`, to more accurately reflect
  their purpose of sending data to the *linker*. Currently, `link_func`
  remains responsible for codegen; this will change in an upcoming
  commit.

* Don't go on a pointless detour through `PerThread` when linking ZCU
  functions/`Nav`s; so, the `linkerUpdateNav` etc logic now lives in
  `link.zig`. Currently, `linkerUpdateFunc` is an exception, because it
  has broader responsibilities including codegen, but this will be
  solved in an upcoming commit.
2025-06-12 13:55:39 +01:00
Jacob Young
0bf8617d96 x86_64: add support for pie executables 2025-06-06 23:42:14 -07:00
Jacob Young
178ee8aef1 Sema: fix invalid pure Air instruction with comptime-known operands 2025-06-06 23:42:14 -07:00
Alex Rønne Petersen
9d534790eb std.Target: Introduce Cpu convenience functions for feature tests.
Before:

* std.Target.arm.featureSetHas(target.cpu.features, .has_v7)
* std.Target.x86.featureSetHasAny(target.cpu.features, .{ .sse, .avx, .cmov })
* std.Target.wasm.featureSetHasAll(target.cpu.features, .{ .atomics, .bulk_memory })

After:

* target.cpu.has(.arm, .has_v7)
* target.cpu.hasAny(.x86, &.{ .sse, .avx, .cmov })
* target.cpu.hasAll(.wasm, &.{ .atomics, .bulk_memory })
2025-06-05 06:12:00 +02:00
mlugg
c1a5caa454 compiler: combine @intCast safety checks
`castTruncatedData` was a poorly worded error (all shrinking casts
"truncate bits", it's just that we assume those bits to be zext/sext of
the other bits!), and `negativeToUnsigned` was a pointless distinction
which forced the compiler to emit worse code (since two separate safety
checks were required for casting e.g. 'i32' to 'u16') and wasn't even
implemented correctly. This commit combines those safety panics into one
function, `integerOutOfBounds`. The name maybe isn't perfect, but that's
not hugely important; what matters is the new default message, which is
clearer than the old ones: "integer does not fit in destination type".
2025-06-01 12:10:57 +01:00
mlugg
add2976a9b compiler: implement better shuffle AIR
Runtime `@shuffle` has two cases which backends generally want to handle
differently for efficiency:

* One runtime vector operand; some result elements may be comptime-known
* Two runtime vector operands; some result elements may be undefined

The latter case happens if both vectors given to `@shuffle` are
runtime-known and they are both used (i.e. the mask refers to them).
Otherwise, if the result is not entirely comptime-known, we are in the
former case. `Sema` now diffentiates these two cases in the AIR so that
backends can easily handle them however they want to. Note that this
*doesn't* really involve Sema doing any more work than it would
otherwise need to, so there's not really a negative here!

Most existing backends have their lowerings for `@shuffle` migrated in
this commit. The LLVM backend uses new lowerings suggested by Jacob as
ones which it will handle effectively. The x86_64 backend has not yet
been migrated; for now there's a panic in there. Jacob will implement
that before this is merged anywhere.
2025-06-01 08:24:01 +01:00
mlugg
4c4dacf81a Legalize: replace safety_checked_instructions
This adds 4 `Legalize.Feature`s:
* `expand_intcast_safe`
* `expand_add_safe`
* `expand_sub_safe`
* `expand_mul_safe`

These do pretty much what they say on the tin. This logic was previously
in Sema, used when `Zcu.Feature.safety_checked_instructions` was not
supported by the backend. That `Zcu.Feature` has been removed in favour
of this legalization.
2025-06-01 08:24:00 +01:00
Jacob Young
6198f7afb7 Sema: remove all_vector_instructions logic
Backends can instead ask legalization on a per-instruction basis.
2025-05-31 18:54:28 -04:00
Jacob Young
b483defc5a Legalize: implement scalarization of binary operations 2025-05-31 18:54:28 -04:00
Jacob Young
c04be630d9 Legalize: introduce a new pass before liveness
Each target can opt into different sets of legalize features.
By performing these transformations before liveness, instructions
that become unreferenced will have up-to-date liveness information.
2025-05-29 03:57:48 -04:00
Jacob Young
8bacf3e757 x86_64: implement integer @reduce(.Max) 2025-05-28 15:10:22 -04:00
Jacob Young
3fd3358f37 x86_64: implement integer @reduce(.Min) 2025-05-28 15:10:22 -04:00
Jacob Young
a4a1ebdeed x86_64: implement optimized float @reduce(.Mul) 2025-05-28 15:10:22 -04:00
mlugg
7c31f9d4ff Sema: don't emit AIR reduce for single-element vectors
This is equivalent to `array_elem_val`, and doing that conversion in
Sema (seems reasonable since it's just a simple branch) is much easier
for the self-hosted x86_64 backend then actually handling this case.
2025-05-28 15:10:22 -04:00
Jacob Young
d69f4c48fc x86_64: rewrite bitwise @reduce 2025-05-28 15:10:22 -04:00
mlugg
92c63126e8 compiler: tlv pointers are not comptime-known
Pointers to thread-local variables do not have their addresses known
until runtime, so it is nonsensical for them to be comptime-known. There
was logic in the compiler which was essentially attempting to treat them
as not being comptime-known despite the pointer being an interned value.
This was a bit of a mess, the check was frequent enough to actually show
up in compiler profiles, and it was very awkward for backends to deal
with, because they had to grapple with the fact that a "constant" they
were lowering might actually require runtime operations.

So, instead, do not consider these pointers to be comptime-known in
*any* way. Never intern such a pointer; instead, when the address of a
threadlocal is taken, emit an AIR instruction which computes the pointer
at runtime. This avoids lots of special handling for TLVs across
basically all codegen backends; of all somewhat-functional backends, the
only one which wasn't improved by this change was the LLVM backend,
because LLVM pretends this complexity around threadlocals doesn't exist.

This change simplifies Sema and codegen, avoids a potential source of
bugs, and potentially improves Sema performance very slightly by
avoiding a non-trivial check on a hot path.
2025-05-27 19:23:11 +01:00
David Rubin
3ed9155f10 Sema: simplify comptime @intFromPtr logic 2025-05-27 02:40:58 +01:00
mlugg
aeed5f9ebd compiler: introduce incremental debug server
In a compiler built with debug extensions, pass `--debug-incremental` to
spawn the "incremental debug server". This is a TCP server exposing a
REPL which allows querying a bunch of compiler state, some of which is
stored only when that flag is passed. Eventually, this will probably
move into `std.zig.Server`/`std.zig.Client`, but this is easier to work
with right now. The easiest way to interact with the server is `telnet`.
2025-05-25 04:43:43 +01:00
Matthew Lugg
23c817548b Merge pull request #23836 from mlugg/incr-fixes
Incremental fixes, refactor `Zcu.File`
2025-05-20 03:25:19 +01:00
mlugg
f2077f57ae Sema: allow @ptrCast single-item pointer to slice
Also, rework this logic a little to make it simpler. The length of the
result slice is now computed in one place.
2025-05-19 19:26:12 +01:00
mlugg
07a5efd072 Sema: rewrite analyzeMinMax
I only wanted to fix a bug originally, but this logic was kind of a
rat's nest. But now... okay, it still *is*, but it's now a slightly more
navigable nest, with cute little signs occasionally, painted by adorable
rats desparately trying to follow the specification.

Hopefully #3806 comes along at some point to simplify this logic a
little.

Resolves: #23139
2025-05-19 00:27:01 +01:00
mlugg
37a9a4e0f1 compiler: refactor Zcu.File and path representation
This commit makes some big changes to how we track state for Zig source
files. In particular, it changes:

* How `File` tracks its path on-disk
* How AstGen discovers files
* How file-level errors are tracked
* How `builtin.zig` files and modules are created

The original motivation here was to address incremental compilation bugs
with the handling of files, such as #22696. To fix this, a few changes
are necessary.

Just like declarations may become unreferenced on an incremental update,
meaning we suppress analysis errors associated with them, it is also
possible for all imports of a file to be removed on an incremental
update, in which case file-level errors for that file should be
suppressed. As such, after AstGen, the compiler must traverse files
(starting from analysis roots) and discover the set of "live files" for
this update.

Additionally, the compiler's previous handling of retryable file errors
was not very good; the source location the error was reported as was
based only on the first discovered import of that file. This source
location also disappeared on future incremental updates. So, as a part
of the file traversal above, we also need to figure out the source
locations of imports which errors should be reported against.

Another observation I made is that the "file exists in multiple modules"
error was not implemented in a particularly good way (I get to say that
because I wrote it!). It was subject to races, where the order in which
different imports of a file were discovered affects both how errors are
printed, and which module the file is arbitrarily assigned, with the
latter in turn affecting which other files are considered for import.
The thing I realised here is that while the AstGen worker pool is
running, we cannot know for sure which module(s) a file is in; we could
always discover an import later which changes the answer.

So, here's how the AstGen workers have changed. We initially ensure that
`zcu.import_table` contains the root files for all modules in this Zcu,
even if we don't know any imports for them yet. Then, the AstGen
workers do not need to be aware of modules. Instead, they simply ignore
module imports, and only spin off more workers when they see a by-path
import.

During AstGen, we can't use module-root-relative paths, since we don't
know which modules files are in; but we don't want to unnecessarily use
absolute files either, because those are non-portable and can make
`error.NameTooLong` more likely. As such, I have introduced a new
abstraction, `Compilation.Path`. This type is a way of representing a
filesystem path which has a *canonical form*. The path is represented
relative to one of a few special directories: the lib directory, the
global cache directory, or the local cache directory. As a fallback, we
use absolute (or cwd-relative on WASI) paths. This is kind of similar to
`std.Build.Cache.Path` with a pre-defined list of possible
`std.Build.Cache.Directory`, but has stricter canonicalization rules
based on path resolution to make sure deduplicating files works
properly. A `Compilation.Path` can be trivially converted to a
`std.Build.Cache.Path` from a `Compilation`, but is smaller, has a
canonical form, and has a digest which will be consistent across
different compiler processes with the same lib and cache directories
(important when we serialize incremental compilation state in the
future). `Zcu.File` and `Zcu.EmbedFile` both contain a
`Compilation.Path`, which is used to access the file on-disk;
module-relative sub paths are used quite rarely (`EmbedFile` doesn't
even have one now for simplicity).

After the AstGen workers all complete, we know that any file which might
be imported is definitely in `import_table` and up-to-date. So, we
perform a single-threaded graph traversal; similar to what
`resolveReferences` plays for `AnalUnit`s, but for files instead. We
figure out which files are alive, and which module each file is in. If a
file turns out to be in multiple modules, we set a field on `Zcu` to
indicate this error. If a file is in a different module to a prior
update, we set a flag instructing `updateZirRefs` to invalidate all
dependencies on the file. This traversal also discovers "import errors";
these are errors associated with a specific `@import`. With Zig's
current design, there is only one possible error here: "import outside
of module root". This must be identified during this traversal instead
of during AstGen, because it depends on which module the file is in. I
tried also representing "module not found" errors in this same way, but
it turns out to be much more useful to report those in Sema, because of
use cases like optional dependencies where a module import is behind a
comptime-known build option.

For simplicity, `failed_files` now just maps to `?[]u8`, since the
source location is always the whole file. In fact, this allows removing
`LazySrcLoc.Offset.entire_file` completely, slightly simplifying some
error reporting logic. File-level errors are now directly built in the
`std.zig.ErrorBundle.Wip`. If the payload is not `null`, it is the
message for a retryable error (i.e. an error loading the source file),
and will be reported with a "file imported here" note pointing to the
import site discovered during the single-threaded file traversal.

The last piece of fallout here is how `Builtin` works. Rather than
constructing "builtin" modules when creating `Package.Module`s, they are
now constructed on-the-fly by `Zcu`. The map `Zcu.builtin_modules` maps
from digests to `*Package.Module`s. These digests are abstract hashes of
the `Builtin` value; i.e. all of the options which are placed into
"builtin.zig". During the file traversal, we populate `builtin_modules`
as needed, so that when we see this imports in Sema, we just grab the
relevant entry from this map. This eliminates a bunch of awkward state
tracking during construction of the module graph. It's also now clearer
exactly what options the builtin module has, since previously it
inherited some options arbitrarily from the first-created module with
that "builtin" module!

The user-visible effects of this commit are:
* retryable file errors are now consistently reported against the whole
  file, with a note pointing to a live import of that file
* some theoretical bugs where imports are wrongly considered distinct
  (when the import path moves out of the cwd and then back in) are fixed
* some consistency issues with how file-level errors are reported are
  fixed; these errors will now always be printed in the same order
  regardless of how the AstGen pass assigns file indices
* incremental updates do not print retryable file errors differently
  between updates or depending on file structure/contents
* incremental updates support files changing modules
* incremental updates support files becoming unreferenced

Resolves: #22696
2025-05-18 17:37:02 +01:00
Jacob Young
a3b0c242b0 x86_64: rewrite @splat 2025-05-17 18:00:17 -04:00
Jacob Young
58d2bd601e x86_64: rewrite scalar <<|
Closes #23035
2025-05-17 18:00:17 -04:00
Jacob Young
6d68a494c8 x86_64: rewrite vector +| 2025-05-17 02:08:41 -04:00
mlugg
4296727050 Sema: improve "called from here" notes
To an average user, it may be unclear why these notes are not just in
the reference trace; that's because they are more important, because
they are inline calls through which comptime values may propagate. There
are now 3 possible wordings for this note:

* "called at comptime here"
* "called inline here"
* "generic function instantiated here"

An alternative could be these wordings:

* "while analyzing comptime call here"
* "while analyzing inline call here"
* "while analyzing generic instantiation here"

I'm not sure which is better -- but this commit is certainly better than
status quo.
2025-05-16 13:28:15 +01:00
mlugg
d717c96877 compiler: include inline calls in the reference trace
Inline calls which happened in the erroring `AnalUnit` still show as
error notes, because they tend to make very important context (e.g. to
see how comptime values propagate through them). However, "earlier"
inline calls are still useful to see to understand how something is
being referenced, so we should include them in the reference trace.
2025-05-16 13:28:15 +01:00
mlugg
70040778fb Compilation: fix reference trace behavior without -freference-trace
When `-freference-trace` is not passed, we want to show exactly one
reference trace. Previously, we set the reference trace root in `Sema`
iff there were no other failed analyses. However, this results in an
arbitrary error being the one with the reference trace after error
sorting. It is also incompatible with incremental compilation, where
some errors might be unreferenced. Instead, set the field on all
analysis errors, and decide in `Compilation.getAllErrorsAlloc` which
reference trace[s] to actually show.
2025-05-16 11:55:35 +01:00
Matthew Lugg
f4e9846bca Merge pull request #23263 from mlugg/comptime-field-ptr
Sema: fix pointers to comptime fields of comptime-known aggregate pointers
2025-05-03 20:10:42 +01:00
Andrew Kelley
8facd99d41 Merge pull request #23708 from ziglang/memmove-followups
`@memmove` followups
2025-04-28 15:06:18 -04:00
mlugg
d038676a1f Sema: fix a few indexing bugs
* Indexing zero-bit types should not produce AIR indexing instructions
* Getting a runtime-known element pointer from a many-pointer should
  check that the many-pointer is not comptime-only

Resolves: #23405
2025-04-28 19:43:58 +01:00
dweiller
365ed0ed68 sema: do checked cast when resolving aggregate size 2025-04-28 16:48:45 +01:00
Andrew Kelley
7bd3207921 make @memcpy and @memmove share panic handlers 2025-04-27 23:30:00 -07:00
xdBronch
410298271e Sema: fix memcpy with C pointers 2025-04-28 05:09:12 +01:00
mlugg
95932e98e5 Sema: fix alignment of runtime field pointer of underaligned tuple 2025-04-28 01:14:24 +01:00
mlugg
d4c5396646 Sema: fix pointers to comptime fields of comptime-known aggregate pointers
Resolves: #23190
2025-04-28 01:14:22 +01:00
Alex Rønne Petersen
5ed8bd5c85 Sema: Fix some ptr alignment checks to handle a potential ISA tag bit.
Closes #23570.
2025-04-27 23:54:54 +01:00
dweiller
898ca82458 compiler: add @memmove builtin 2025-04-26 13:34:16 +10:00
mlugg
8c9c24e09b compiler: integrate @compileLog with incremental compilation
Compile log output is now separated based on the `AnalUnit` which
perfomred the `@compileLog` call, so that we can omit the output for
unreferenced ("dead") units. The units are also sorted when collecting
the `ErrorBundle`, so that compile logs are always printed in a
consistent order, like compile errors are. This is important not only
for incremental compilation, but also for parallel analysis.

Resolves: #23609
2025-04-20 18:11:53 +01:00
Jacob Young
06eebafadd AstGen: redistribute inline asm limits 2025-04-10 06:04:09 -04:00
Alex Rønne Petersen
7415739e36 Sema: Prevent tail calls of std.builtin.returnError().
LLVM 20 started tail-calling it in some of our test cases, resulting in:

    error: AndMyCarIsOutOfGas
    /home/alexrp/Source/ziglang/zig-llvm20/repro.zig:2:5: 0x103ef9d in main (repro)
        return error.TheSkyIsFalling;
        ^
    /home/alexrp/Source/ziglang/zig-llvm20/repro.zig:6:5: 0x103efa5 in main (repro)
        return error.AndMyCarIsOutOfGas;
        ^
    /home/alexrp/Source/ziglang/zig-llvm20/lib/std/start.zig:656:37: 0x103ee83 in posixCallMainAndExit (repro)
                const result = root.main() catch |err| {
                                        ^

instead of the expected:

    error: AndMyCarIsOutOfGas
    /home/alexrp/Source/ziglang/zig-llvm20/repro.zig:2:5: 0x103f00d in main (repro)
        return error.TheSkyIsFalling;
        ^
    /home/alexrp/Source/ziglang/zig-llvm20/repro.zig:6:5: 0x103f015 in main (repro)
        return error.AndMyCarIsOutOfGas;
        ^
    /home/alexrp/Source/ziglang/zig-llvm20/repro.zig:11:9: 0x103f01d in main (repro)
            try bar();
            ^
2025-04-04 06:08:10 +02:00
Mason Remaley
06ee383da9 compiler: allow @import of ZON without a result type
In particular, this allows importing `build.zig.zon` at comptime.
2025-04-02 05:53:22 +01:00
David Rubin
1b62a22268 Sema: increment extra index even if return type is generic 2025-04-02 01:34:17 +02:00