147 Commits

Author SHA1 Message Date
Andrew Kelley
9be8a9000f Revert "implement @expect builtin (#19658)"
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-22 09:57:43 -07:00
David Rubin
a7de02e052
implement @expect builtin (#19658)
* 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-22 10:51:16 -05: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
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
Veikka Tuominen
7d75c3d3b8 llvm: ensure returned undef is 0xaa bytes when runtime safety is enabled
Closes #13178
2024-01-29 17:35:07 -08:00
Andrew Kelley
9d5a133f18 Revert "Don't assume a write if an operand is not in function parameters"
This reverts commit 2ab78937dd29fbc299ac434f962a5ff41002cc43.

Premature merge - apologies for the disruption.

Reopens #15685
Reopens #17580
2024-01-23 20:24:58 -07:00
Rahul Prabhu
2ab78937dd Don't assume a write if an operand is not in function parameters
Liveness assumes that if the operand is not in the parameters of
a function call it is being written to, resulting in pointless memcpies.
2024-01-23 18:32:34 -08:00
arbrk1
024540de15
Liveness: fix branch operands becoming aliased 2024-01-02 12:08:26 +02:00
Jacob Young
daf91ed8d1 Air: use typesafe Air.Inst.Index
I need some indices for a thing...
2023-12-03 02:05:06 -08:00
antlilja
6a29646a55 Rename @fabs to @abs and accept integers
Replaces the @fabs builtin with a new @abs builtins which accepts
floats, signed integers and vectors of said types.
2023-09-27 11:15:53 -07:00
mlugg
ff37ccd298 Air: store interned values in Air.Inst.Ref
Previously, interned values were represented as AIR instructions using
the `interned` tag. Now, the AIR ref directly encodes the InternPool
index. The encoding works as follows:
* If the ref matches one of the static values, it corresponds to the same InternPool index.
* Otherwise, if the MSB is 0, the ref corresponds to an InternPool index.
* Otherwise, if the MSB is 1, the ref corresponds to an AIR instruction index (after removing the MSB).

Note that since most static InternPool indices are low values (the
exceptions being `.none` and `.var_args_param_type`), the first rule is
almost a nop.
2023-06-27 01:21:32 -07:00
Andrew Kelley
9684947faa compiler: start moving safety-checks into backends
This actually used to be how it worked in stage1, and there was this
issue to change it: #2649

So this commit is a reversal to that idea. One motivation for that issue
was avoiding emitting the panic handler in compilations that do not have
any calls to panic. This commit only resolves the panic handler in the
event of a safety check function being emitted, so it does not have that
flaw.

The other reason given in that issue was for optimizations that elide
safety checks. It's yet to be determined whether that was a good idea or
not; this can get re-explored when we start adding optimization passes
to AIR.

This commit adds these AIR instructions, which are only emitted if
`backendSupportsFeature(.safety_checked_arithmetic)` is true:
 * add_safe
 * sub_safe
 * mul_safe

It removes these nonsensical AIR instructions:
 * addwrap_optimized
 * subwrap_optimized
 * mulwrap_optimized

The safety-checked arithmetic functions push the burden of invoking the
panic handler into the backend. This makes for a messier compiler
implementation, but it reduces the amount of AIR instructions emitted by
Sema, which reduces time spent in the secondary bottleneck of the
compiler. It also generates more compact LLVM IR, reducing time spent in
the primary bottleneck of the compiler.

Finally, it eliminates 1 stack allocation per safety-check which was
being used to store the resulting tuple. These allocations were going to
be annoying when combined with suspension points.
2023-06-25 01:41:08 -07:00
Andrew Kelley
82ad66b2f2 liveness: fix merge typo logic error
Oops, I made a terrible mistake when applying a small fixup when merging
f10b9e8fd72aae33b127c18e3f8a64a4f56b1b69.
2023-06-25 01:02:55 -07:00
mlugg
f26dda2117 all: migrate code to new cast builtin syntax
Most of this migration was performed automatically with `zig fmt`. There
were a few exceptions which I had to manually fix:

* `@alignCast` and `@addrSpaceCast` cannot be automatically rewritten
* `@truncate`'s fixup is incorrect for vectors
* Test cases are not formatted, and their error locations change
2023-06-24 16:56:39 -07:00
Xavier Bouchoux
f10b9e8fd7 update Liveness to detect that safety checks do not modify memory
followup to [25d3713b07a100d8fdb349317db97fd9d0c1e366]
Resolves #12215

Previous code didn't account for the extra unreach() that now exists in the air:

```
 %29!= block(void, {
    %30!= cond_br(%22!, {
      %31!= br(%29, @Air.Inst.Ref.void_value)
    }, {
      %2! %15!
      %27!= call(%26, [%19!, %21])
      %28!= unreach()
    })
  } %22!)
```
2023-06-24 12:57:46 -07:00
Eric Joldasov
50339f595a all: zig fmt and rename "@XToY" to "@YFromX"
Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>
2023-06-19 12:34:42 -07:00
Eric Joldasov
a6c8ee5231 compiler: rename "@XToY" to "@YFromX", zig fmt: rewrite them
Signed-off-by: Eric Joldasov <bratishkaerik@getgoogleoff.me>
2023-06-19 12:34:24 -07:00
Andrew Kelley
90a877f462 InternPool: pass by const pointer
The Zig language allows the compiler to make this optimization
automatically. We should definitely make the compiler do that, and
revert this commit. However, that will not happen in this branch, and I
want to continue to explore achieving performance parity with
merge-base. So, this commit changes all InternPool parameters to be
passed by const pointer rather than by value.

I measured a 1.03x ± 0.03 speedup vs the previous commit compiling the
(set of passing) behavior tests. Against merge-base, this commit is
1.17x ± 0.04 slower, which is an improvement from the previous
measurement of 1.22x ± 0.02.

Related issue: #13510
Related issue: #14129
Related issue: #15688
2023-06-10 20:47:57 -07:00
Jacob Young
70cc68e999 Air: remove constant tag
Some uses have been moved to their own tag, the rest use interned.

Also, finish porting comptime mutation to be more InternPool aware.
2023-06-10 20:47:55 -07:00
Jacob Young
1a4626d2cf InternPool: remove more legacy values
Reinstate some tags that will be needed for comptime init.
2023-06-10 20:47:54 -07:00
Andrew Kelley
9ff514b6a3 compiler: move error union types and error set types to InternPool
One change worth noting in this commit is that `module.global_error_set`
is no longer kept strictly up-to-date. The previous code reserved
integer error values when dealing with error set types, but this is no
longer needed because the integer values are not needed for semantic
analysis unless `@errorToInt` or `@intToError` are used and therefore
may be assigned lazily.
2023-06-10 20:47:53 -07:00
Andrew Kelley
2f05b1482a Sema: update core comptime detection logic to be InternPool aware
* Add some assertions to make sure instructions are not none. I tested
   all these with master branch as well and made sure the behavior tests
   still passed with the assertions intact (along with a handful of
   callsite updates).
 * Fix Sema.resolveMaybeUndefValAllowVariablesMaybeRuntime not noticing
   that interned values are comptime-known. This was causing all kinds
   of chaos.
 * Fix print_air writeType calling tag() without checking for ip_index
2023-06-10 20:42:28 -07:00
Andrew Kelley
5e636643d2 stage2: move many Type encodings to InternPool
Notably, `vector`.

Additionally, all alternate encodings of `pointer`, `optional`, and
`array`.
2023-06-10 20:42:27 -07:00
Andrew Kelley
00f82f1c46 stage2: add interned AIR tag
This required additionally passing the `InternPool` into some AIR
methods.

Also, implement `Type.isNoReturn` for interned types.
2023-06-10 20:40:03 -07:00
Andrew Kelley
9aec2758cc stage2: start the InternPool transition
Instead of doing everything at once which is a hopelessly large task,
this introduces a piecemeal transition that can be done in small
increments at a time.

This is a minimal changeset that keeps the compiler compiling. It only
uses the InternPool for a small set of types.

Behavior tests are not passing.

Air.Inst.Ref and Zir.Inst.Ref are separated into different enums but
compile-time verified to have the same fields in the same order.

The large set of changes is mainly to deal with the fact that most Type
and Value methods now require a Module to be passed in, so that the
InternPool object can be accessed.
2023-06-10 20:40:03 -07:00
mlugg
214f2fc395 Liveness: simplify logic
`branch_deaths` was a relic from before I had a full understanding of
AIR's control flow structure, and so was unnecessary. This change
simplifies Liveness, fixes a bug exposed by #15235, and likely improves
performance (due to cloning hashmaps less often).
2023-05-12 00:01:52 +03:00
Andrew Kelley
42973d73e6 compiler: use @memcpy instead of std.mem.copy 2023-04-28 13:24:43 -07:00
Andrew Kelley
6261c13731 update codebase to use @memset and @memcpy 2023-04-28 13:24:43 -07:00
Andrew Kelley
5378fdffdc stage2: introduce store_safe AIR instruction
store:
The value to store may be undefined, in which case the destination
memory region has undefined bytes after this instruction is
evaluated. In such case ignoring this instruction is legal
lowering.

store_safe:
Same as `store`, except if the value to store is undefined, the
memory region should be filled with 0xaa bytes, and any other
safety metadata such as Valgrind integrations should be notified of
this memory region being undefined.
2023-04-25 11:23:41 -07:00
Andrew Kelley
057c950093 LLVM backend: support non-byte-sized memset
Also introduce memset_safe AIR tag and support it in C backend and LLVM
backend.
2023-04-25 11:23:41 -07:00
Andrew Kelley
a5c910adb6 change semantics of @memcpy and @memset
Now they use slices or array pointers with any element type instead of
requiring byte pointers.

This is a breaking enhancement to the language.

The safety check for overlapping pointers will be implemented in a
future commit.

closes #14040
2023-04-25 11:23:40 -07:00
mlugg
407dc6eee4
Liveness: avoid emitting unused instructions or marking their operands as used
Backends want to avoid emitting unused instructions which do not have
side effects: to that end, they all have `Liveness.isUnused` checks for
many instructions. However, checking this in the backends avoids a lot
of potential optimizations. For instance, if a nested field is loaded,
then the first field access would still be emitted, since its result is
used by the next access (which is then unreferenced).

To elide more instructions, Liveness can track this data instead. For
operands which do not have to be lowered (i.e. are not side effecting
and are not something special like `arg), Liveness can ignore their
operand usages, and push the unused information further up, potentially
marking many more instructions as unreferenced.

In doing this, I also uncovered a bug in the LLVM backend relating to
discarding the result of `@cVaArg`, which this change fixes. A behaviour
test has been added to cover it.
2023-04-20 20:28:48 +01:00
Jacob Young
02a8b66b00
Liveness: add a liveness verification pass
This code only runs in a debug zig compiler, similar to verifying llvm modules.
2023-04-20 20:28:47 +01:00
mlugg
8258530c39
Liveness: control flow analysis
This is a partial rewrite of Liveness, so has some other notable changes:
- A proper multi-pass system to prevent code duplication
- Better logging
- Minor bugfixes
2023-04-20 20:28:04 +01:00
mlugg
1059b57898
Liveness: defer deaths of externally-scoped instructions in loop bodies 2023-04-07 01:29:20 +01:00
Robin Voetter
3357c59ceb new builtins: @workItemId, @workGroupId, @workGroupSize
* @workItemId returns the index of the work item in a work group for a
  dimension.
* @workGroupId returns the index of the work group in the kernel dispatch for a
  dimension.
* @workGroupSize returns the size of the work group for a dimension.

These builtins are mainly useful for GPU backends. They are currently only
implemented for the AMDGCN LLVM backend.
2023-03-30 12:20:24 +03:00
r00ster91
65368683ad add @trap builtin
This introduces a new builtin function that compiles down to something that results in an illegal instruction exception/interrupt.
It can be used to exit a program abnormally.

This implements the builtin for all backends.
2023-03-04 12:08:19 +01:00
Andrew Kelley
aeaef8c0ff update std lib and compiler sources to new for loop syntax 2023-02-18 19:17:21 -07:00
Andrew Kelley
aca9c74e80
Merge pull request #13914 from Vexu/variadic
implement defining C variadic functions
2022-12-18 16:24:13 -05:00
r00ster91
aac2d6b56f std.builtin: rename Type.UnionField and Type.StructField's field_type to type 2022-12-17 14:11:33 +01:00
Veikka Tuominen
9bb1104e37 implement defining C variadic functions 2022-12-17 13:22:09 +02:00
Veikka Tuominen
8a0a6b7387 port packed vector elem ptr logic from stage1
Closes #12812
Closes #13925
2022-12-15 21:06:35 -05:00
Cody Tapscott
25d3713b07 stage2: Teach Liveness that safety checks do not modify memory
This change adds to Liveness a simple pattern match for the
try-like `.condbr` blocks emitted by Sema's safety checks. This
allows us to determine that these do not modify memory, which
permits us to elide additional loads in the backend.

As @Vexu points out in the main issue, this is probably not a
complete solution on its own. We'll still want a way to reliably
narrow the load/copy when performing several consecutive accesses,
such as `foo.arr[x][y].z`

Resolves https://github.com/ziglang/zig/issues/12215
2022-12-12 18:48:10 -05:00
Andrew Kelley
ceb0a632cf std.mem.Allocator: allow shrink to fail
closes #13535
2022-11-29 23:30:38 -07:00
Cody Tapscott
724d753638 stage2: Add .save_err_return_trace_index AIR op
This is encoded as a primitive AIR instruction to resolve one corner
case: A function may include a `catch { ... }` or `else |err| { ... }`
block but not call any errorable fn. In that case, there is no error
return trace to save the index of and codegen needs to avoid
interacting with the non-existing error trace.

By using a primitive AIR op, we can depend on Liveness to mark this
unused in this corner case.
2022-10-21 10:44:20 -07:00
Robin Voetter
5d429b03e3
stage2: add @addrSpaceCast builtin 2022-10-12 20:36:12 +02:00
Veikka Tuominen
7c9979a02e stage2: generate a switch for @errSetCast safety 2022-08-12 11:40:37 +03:00
Veikka Tuominen
f46d7304b1 stage2: add runtime safety for invalid enum values 2022-08-05 22:13:58 +03:00
Veikka Tuominen
d75fa86d70 stage2: implement @setFloatMode 2022-07-23 15:40:12 +03:00