Commit Graph

332 Commits

Author SHA1 Message Date
mlugg
d0e74ffe52 compiler: rework comptime pointer representation and access
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-17 13:41:25 +01:00
Jacob Young
7611d90ba0 InternPool: remove slice from byte aggregate keys
This deletes a ton of lookups and avoids many UAF bugs.

Closes #19485
2024-04-08 13:24:08 -04:00
Robin Voetter
97a67762ba spirv: remove cache usage for types 2024-04-06 13:37:39 +02:00
Robin Voetter
188922a544 spirv: remove cache usage for constants 2024-04-06 13:37:39 +02:00
Robin Voetter
42c7e752e1 spirv: id range helper
This allows us to more sanely allocate a continuous
range of result-ids, and avoids a bunch of nasty
casting code in a few places. Its currently not used
very often, but will be useful in the future.
2024-04-06 13:37:37 +02:00
Ali Chraghi
436f53f55d spirv: implement @mulWithOverflow 2024-04-06 09:01:46 +03:30
Ali Chraghi
9785014938 spirv: OpExtInstImport in assembler 2024-04-06 08:52:38 +03:30
Ali Chraghi
0f75143c62 spirv: implement @divFloor, @floor and @mod 2024-04-06 08:50:02 +03:30
Ali Chraghi
14e3718723 spirv: make behavior tests passing 2024-04-05 00:13:48 +03:30
Robin Voetter
12350f53bf spirv: clz, ctz for opencl
This instruction seems common in compiler_rt.
2024-03-30 19:47:55 +01:00
mlugg
2a245e3b78 compiler: eliminate TypedValue
The only logic which remained in this file was the Value printing logic.
This has been moved into a new `print_value.zig`.
2024-03-26 13:48:07 +00:00
mlugg
26a94e8481 Zcu: eliminate Decl.alive field
Legacy anon decls now have three uses:
* Type owner decls
* Function owner decls
* `@export` and `@extern`

Therefore, there are no longer any cases where we wish to explicitly
omit legacy anon decls from the binary. This means we can remove the
concept of an "alive" vs "dead" `Decl`, which also allows us to remove
the separate `anon_work_queue` in `Compilation`.
2024-03-26 13:48:06 +00:00
mlugg
c6f3e9d79c Zcu.Decl: remove ty field
`Decl` can no longer store un-interned values, so this field is now
unnecessary. The type can instead be fetched with the new `typeOf`
helper method, which just gets the type of the Decl's `Value`.
2024-03-26 13:48:06 +00:00
mlugg
9c3670fc93 compiler: implement analysis-local comptime-mutable memory
This commit changes how we represent comptime-mutable memory
(`comptime var`) in the compiler in order to implement the intended
behavior that references to such memory can only exist at comptime.

It does *not* clean up the representation of mutable values, improve the
representation of comptime-known pointers, or fix the many bugs in the
comptime pointer access code. These will be future enhancements.

Comptime memory lives for the duration of a single Sema, and is not
permitted to escape that one analysis, either by becoming runtime-known
or by becoming comptime-known to other analyses. These restrictions mean
that we can represent comptime allocations not via Decl, but with state
local to Sema - specifically, the new `Sema.comptime_allocs` field. All
comptime-mutable allocations, as well as any comptime-known const allocs
containing references to such memory, live in here. This allows for
relatively fast checking of whether a value references any
comptime-mtuable memory, since we need only traverse values up to
pointers: pointers to Decls can never reference comptime-mutable memory,
and pointers into `Sema.comptime_allocs` always do.

This change exposed some faulty pointer access logic in `Value.zig`.
I've fixed the important cases, but there are some TODOs I've put in
which are definitely possible to hit with sufficiently esoteric code. I
plan to resolve these by auditing all direct accesses to pointers (most
of them ought to use Sema to perform the pointer access!), but for now
this is sufficient for all realistic code and to get tests passing.

This change eliminates `Zcu.tmp_hack_arena`, instead using the Sema
arena for comptime memory mutations, which is possible since comptime
memory is now local to the current Sema.

This change should allow `Decl` to store only an `InternPool.Index`
rather than a full-blown `ty: Type, val: Value`. This commit does not
perform this refactor.
2024-03-25 14:49:41 +00:00
Robin Voetter
335ff5a5f4 spirv: fix optional comparison 2024-03-18 19:13:50 +01:00
Robin Voetter
9b18125562 spirv: make generic globals invocation-local 2024-03-18 19:13:50 +01:00
Robin Voetter
e566158acf spirv: make IdResult an enum 2024-03-18 19:13:49 +01:00
Robin Voetter
3bffa58012 Revert "spirv: merge construct(Struct/Vector/Array) into constructComposite"
This reverts commit eb2d61d02e.
2024-03-17 14:17:26 +01:00
Tristan Ross
099f3c4039 std.builtin: make container layout fields lowercase 2024-03-11 07:09:07 -07:00
mlugg
975b859377 InternPool: create specialized functions for loading namespace types
Namespace types (`struct`, `enum`, `union`, `opaque`) do not use
structural equality - equivalence is based on their Decl index (and soon
will change to AST node + captures). However, we previously stored all
other information in the corresponding `InternPool.Key` anyway. For
logical consistency, it makes sense to have the key only be the true key
(that is, the Decl index) and to load all other data through another
function. This introduces those functions, by the name of
`loadStructType` etc. It's a big diff, but most of it is no-brainer
changes.

In future, it might be nice to eliminate a bunch of the loaded state in
favour of accessor functions on the `LoadedXyzType` types (like how we
have `LoadedUnionType.size()`), but that can be explored at a later
date.
2024-03-06 21:26:37 +00:00
Jacob Young
aa688567f5 Air: replace .dbg_inline_* with .dbg_inline_block
This prevents the possibility of not emitting a `.dbg_inline_end`
instruction and reduces the allocation requirements of the backends.

Closes #19093
2024-03-02 21:19:34 -08:00
Andrew Kelley
7b37bc771b move Zir to std.zig.Zir
Part of an effort to ship more of the compiler in source form.
2024-02-26 21:35:30 -07:00
Andrew Kelley
f7143e18e3 move Zcu.LazySrcLoc to std.zig.LazySrcLoc
Part of an effort to ship more of the compiler in source form.
2024-02-26 21:35:30 -07:00
mlugg
59447e5305 compiler: decide dbg_var scoping based on AIR blocks
This commit eliminates the `dbg_block_{begin,end}` instructions from
both ZIR and AIR. Instead, lexical scoping of `dbg_var_{ptr,val}`
instructions is decided based on the AIR block they exist within. This
is a much more robust system, and also results in a huge drop in ZIR
bytes - around 7% for Sema.zig.

This required some enhancements to Sema to prevent elision of blocks
when they are required for debug variable scoping. This can be observed
by looking at the AIR for the following simple test program with and
without `-fstrip`:

```zig
export fn f() void {
    {
        var a: u32 = 0;
        _ = &a;
    }
    {
        var a: u32 = 0;
        _ = &a;
    }
}
```

When `-fstrip` is passed, no AIR blocks are generated. When `-fno-strip`
is passed, the ZIR blocks are lowered to true AIR blocks to give correct
lexical scoping to the debug vars.

The changes here incidentally reolve #19060. A corresponding behavior
test has been added.

Resolves: #19060
2024-02-26 13:20:45 +00:00
Jacob Young
d656c2a7ab test: rework how filtering works
* make test names contain the fully qualified name
 * make test filters match the fully qualified name
 * allow multiple test filters, where a test is skipped if it does not
   match any of the specified filters
2024-02-25 19:12:08 -08:00
Ali Chraghi
44c31194e3 spirv: use extended instructions whenever possible 2024-02-15 17:25:44 +03:30
Ali Chraghi
72bd1cd378 spirv: remove now-redundant isUnused calls from AIR handler functions 2024-02-10 09:50:02 +03:30
Ali Chraghi
5ee96688a7 spirv: emit vectorized operations 2024-02-09 16:40:34 +03:30
Ali Chraghi
eb2d61d02e spirv: merge construct(Struct/Vector/Array) into constructComposite 2024-02-09 09:27:05 +03:30
Andrew Kelley
78f15bc714 compiler: rename value.zig to Value.zig
This commit only does the file rename to be friendlier to version
control conflicts.
2024-02-05 18:13:07 -07:00
Ali Chraghi
b41aad0193 spirv: emit vectors whenever we can 2024-02-05 11:55:14 +03:30
Ali Chraghi
afa7793351 spirv: basic shader support 2024-02-05 11:55:14 +03:30
Robin Voetter
2511106150 spirv: air vector_store_element 2024-02-04 19:09:34 +01:00
Robin Voetter
1d548aa2aa spirv: air splat 2024-02-04 19:09:33 +01:00
Robin Voetter
76d5696434 spirv: air abs 2024-02-04 19:09:32 +01:00
Robin Voetter
631d1b63a8 spirv: fix shuffle properly 2024-02-04 19:09:32 +01:00
Robin Voetter
9641d2ebdb spirv: vectorize max, min 2024-02-04 19:09:31 +01:00
Robin Voetter
9f0227a326 spirv: vectorize int_cast, trunc 2024-02-04 19:09:31 +01:00
Robin Voetter
408c117246 spirv: air is_(non_)null_ptr, optional_payload_ptr 2024-02-04 19:09:30 +01:00
Robin Voetter
7dfd403da1 spirv: air mul_add 2024-02-04 19:09:30 +01:00
Robin Voetter
345d6e280d spirv: air int_from_bool 2024-02-04 19:09:29 +01:00
Robin Voetter
77ef78a0ef spirv: clean up arithmeticTypeInfo a bit
- No longer returns an error
- Returns more useful vector info
2024-02-04 19:09:29 +01:00
Robin Voetter
54ec936549 spirv: wrap strange its before instead of after operation
Wrapping strange integers before an operation was initially
done as an attempt to minimize the amount of normalizations
required: This way, there would not be a normalization
necessary between two modular operations. This was a
premature optimization, since the resulting logic is more
complicated than naive way of wrapping the result after
the operation.

This commit updates handling of strange integers to do
wrapping after each operation. It also seems slightly
more efficient in terms of size of generated code, as
it reduces the size of the behavior tests binary by
about 1%.
2024-02-04 19:09:28 +01:00
Robin Voetter
b67d983abd spirv: vectorize add/sub overflow 2024-02-04 19:09:27 +01:00
Robin Voetter
761594e226 spirv: reduce, reduce_optimized 2024-02-04 19:09:27 +01:00
Robin Voetter
2f815853dc spirv: shlWithOverflow 2024-02-04 19:09:26 +01:00
Robin Voetter
15cf5f88c1 spirv: vectors for air not 2024-02-04 19:09:25 +01:00
Robin Voetter
403c6262bb spirv: use new vector stuff for arithOp and shift 2024-02-04 19:09:18 +01:00
Robin Voetter
cb9e20da00 spirv: element-wise operation helper 2024-02-04 19:09:00 +01:00
Robin Voetter
747f4ae3f5 spirv: sh[rl](_exact)? 2024-02-04 19:08:59 +01:00