136 Commits

Author SHA1 Message Date
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
Andrew Kelley
6bc6e47b15 stage2: lower float negation explicitly
Rather than lowering float negation as `0.0 - x`.

 * Add AIR instruction for float negation.
 * Add compiler-rt functions for f128, f80 negation

closes #11853
2022-06-30 00:02:00 -07:00
Andrew Kelley
ef885a78d6 stage2: implement the new "try" ZIR/AIR instruction
Implements semantic analysis for the new try/try_inline ZIR
instruction. Adds the new try/try_ptr AIR instructions and implements
them for the LLVM backend.

Fixes not calling rvalue() for tryExpr in AstGen.

This is part of an effort to implement #11772.
2022-06-05 10:37:08 +02:00
Andrew Kelley
d410693dad LLVM: elide some loads when lowering
Generally, the load instruction may need to make a copy of an
isByRef=true value, such as in the case of the following code:

```zig
pub fn swap(comptime T: type, a: *T, b: *T) void {
    const tmp = a.*;
    a.* = b.*;
    b.* = tmp;
}
```

However, it only needs to do so if there are any instructions which can
possibly write to memory. When calling functions with isByRef=true
parameters, the AIR code that is generated looks like loads followed
directly by call.

This allows for a peephole optimization when lowering loads: if the load
instruction operates on an isByRef=true type and dies before any side effects
occur, then we can safely lower the load as a no-op that returns its
operand.

This is one out of three changes I intend to make to address #11498.
However I will put these changes in separate branches and merge them
separately so that we can have three independent points on the perf
charts.
2022-05-31 14:17:54 -04:00
Andrew Kelley
b6798c26ef stage2: fix pointer arithmetic result type
This makes it so the result of doing pointer arithmetic creates a new
pointer type that has adjusted alignment.
2022-05-17 23:50:38 -07:00
Veikka Tuominen
eee8fffec7 stage2: implement error return traces 2022-05-16 17:42:51 -07:00
Andrew Kelley
09f1d62bdf add new builtin function @tan
The reason for having `@tan` is that we already have `@sin` and `@cos`
because some targets have machine code instructions for them, but in the
case that the implementation needs to go into compiler-rt, sin, cos, and
tan all share a common dependency which includes a table of data. To
avoid duplicating this table of data, we promote tan to become a builtin
alongside sin and cos.

ZIR: The tag enum is at capacity so this commit moves
`field_call_bind_named` to be `extended`. I measured this as one of
the least used tags in the zig codebase.

Fix libc math suffix for `f32` being wrong in both stage1 and stage2.
stage1: add missing libc prefix for float functions.
2022-04-27 16:45:23 -07:00
Andrew Kelley
2587474717 stage2: progress towards stage3
* The `@bitCast` workaround is removed in favor of `@ptrCast` properly
   doing element casting for slice element types. This required an
   enhancement both to stage1 and stage2.
 * stage1 incorrectly accepts `.{}` instead of `{}`. stage2 code that
   abused this is fixed.
 * Make some parameters comptime to support functions in switch
   expressions (as opposed to making them function pointers).
 * Avoid relying on local temporaries being mutable.
 * Workarounds for when stage1 and stage2 disagree on function pointer
   types.
 * Workaround recursive formatting bug with a `@panic("TODO")`.
 * Remove unreachable `else` prongs for some inferred error sets.

All in effort towards #89.
2022-04-14 10:12:45 -07:00
Andrew Kelley
b0edd8752a Liveness: modify encoding to support over 32 operands
Prior to this, Liveness encoded `asm`, `call`, and `aggregate_init` with
a single 32-bit integer, allowing up to 35 operands (3 are provided by
the regular tomb_bits). However, the Zig language allows function calls
with more than 35 arguments, inline assembly with more than 35 inputs,
and anonymous tuples with more than 35 elements.

The new encoding stores an index to the extra array instead of the bits
directly, and then as many extra elements as needed to encode all the
operands. The MSB is used as a flag to tell which element is the last
one, allowing for 31 bits per element.

Prior to this, print_air did not bother correctly printing tombstones
for these instructions; now it does.

In addition to updating the BigTomb iteration logic in the machine code
backends, this commit extracts the common logic into the Liveness namespace.
2022-04-12 11:22:12 -07:00
Andrew Kelley
6ae8fe193b Liveness: utilize Air.refToIndex 2022-04-07 23:19:19 -07:00
Andrew Kelley
05947ea870 stage2: implement @intToError with safety
This commit introduces a new AIR instruction `cmp_lt_errors_len`. It's
specific to this use case for two reasons:

 * The total number of errors is not stable during semantic analysis; it
   can only be reliably checked when flush() is called. So the backend
   that is lowering the instruction must emit a relocation of some kind
   and then populate it during flush().
 * The fewer AIR instructions in memory, the better for compiler
   performance, so we squish complex meanings into AIR tags without
   hesitation.

The instruction is implemented only in the LLVM backend so far. It does
this by creating a simple function which is gutted and re-populated
with each flush().

AstGen now uses ResultLoc.coerced_ty for `@intToError` and Sema does the
coercion.
2022-03-29 22:19:06 -07:00
joachimschmidt557
e2468e3f27
Sema: change zirOverflowArithmetic to use new version of AIR insts
Also applies the change to Liveness
2022-03-26 17:21:42 +01:00