Commit graph

697 commits

Author SHA1 Message Date
Jacob Young
2cb52235b9 llvm: convert all calls to constInt 2023-07-19 23:38:40 -04:00
Jacob Young
65fd401c06 llvm: remove more usages of llvm.Type 2023-07-19 23:38:40 -04:00
Jacob Young
d167bd4b56 llvm: finish converting lowerType 2023-07-19 23:38:40 -04:00
Jacob Young
3314fd83af llvm: compute data layout without help like a grownup compiler 2023-07-19 23:38:40 -04:00
Jacob Young
d195173ba2 llvm: start tracking more things without relying on the llvm api 2023-07-19 23:38:40 -04:00
Andrew Kelley
f3dc53f6b5 compiler: rework inferred error sets
* move inferred error sets into InternPool.
   - they are now represented by pointing directly at the corresponding
     function body value.
 * inferred error set working memory is now in Sema and expires after
   the Sema for the function corresponding to the inferred error set is
   finished having its body analyzed.
 * error sets use a InternPool.Index.Slice rather than an actual slice
   to avoid lifetime issues.
2023-07-18 19:02:05 -07:00
Andrew Kelley
db33ee45b7 rework generic function calls
Abridged summary:

 * Move `Module.Fn` into `InternPool`.
 * Delete a lot of confusing and problematic `Sema` logic related to
   generic function calls.

This commit removes `Module.Fn` and replaces it with two new
`InternPool.Tag` values:

 * `func_decl` - corresponding to a function declared in the source
   code. This one contains line/column numbers, zir_body_inst, etc.

 * `func_instance` - one for each monomorphization of a generic
   function. Contains a reference to the `func_decl` from whence the
   instantiation came, along with the `comptime` parameter values (or
   types in the case of `anytype`)

Since `InternPool` provides deduplication on these values, these fields
are now deleted from `Module`:

 * `monomorphed_func_keys`
 * `monomorphed_funcs`
 * `align_stack_fns`

Instead of these, Sema logic for generic function instantiation now
unconditionally evaluates the function prototype expression for every
generic callsite. This is technically required in order for type
coercions to work. The previous code had some dubious, probably wrong
hacks to make things work, such as `hashUncoerced`. I'm not 100% sure
how we were able to eliminate that function and still pass all the
behavior tests, but I'm pretty sure things were still broken without
doing type coercion for every generic function call argument.

After the function prototype is evaluated, it produces a deduplicated
`func_instance` `InternPool.Index` which can then be used for the
generic function call.

Some other nice things made by this simplification are the removal of
`comptime_args_fn_inst` and `preallocated_new_func` from `Sema`, and the
messy logic associated with them.

I have not yet been able to measure the perf of this against master
branch. On one hand, it reduces memory usage and pointer chasing of the
most heavily used `InternPool` Tag - function bodies - but on the other
hand, it does evaluate function prototype expressions more than before.
We will soon find out.
2023-07-18 19:02:05 -07:00
Luuk de Gram
37e2a04da8
add stand alone test to verify bulk-memory features
This adds a standalone test case to ensure the runtime does not trap
when performing a memory.copy or memory.fill instruction while the
destination or source address is out-of-bounds and the length is 0.
2023-07-10 20:05:13 +02:00
Luuk de Gram
d54ebf4356
llvm: add safety-check for Wasm memset
When lowering the `memset` instruction, LLVM will lower it to WebAssembly's
`memory.fill` instruction when the bulk-memory feature is enabled. This
instruction will trap when the destination address is out-of-bounds.
By Zig's semantics, it is valid to have an invalid pointer when the length is 0.
To prevent runtimes from trapping, we add a safety-check for slices to only
lower to a memset instruction when the length is larger than 0.
2023-07-08 17:45:05 +02:00
Luuk de Gram
836f9fceab
llvm: add safety-check for Wasm memcpy
When lowering the `memcpy` instruction, LLVM will lower it to WebAssembly's
`memory.copy` instruction when the bulk-memory feature is enabled. This
instruction will trap when the destination or source pointer is out-of-bounds.
By Zig's semantics, it is valid to have an invalid pointer when the length is 0.
To prevent runtimes from trapping, we add a safety-check for slices to only
lower to a memcpy instruction when the length is larger than 0.
2023-07-08 17:45:04 +02:00
Robin Voetter
13c0624f23
llvm: cast optional null ptr representation to generic address space
The panic handler expects that this value is represented with the
generic address space, so cast the global to the generic address-
space before caching and returning the value.
2023-07-01 20:28:17 +02: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
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
Andrew Kelley
a5e15eced0 LLVM: move many DeclGen methods to Object
DeclGen/FuncGen methods are for things that pertain to a particular
declaration or function, while Object methods are for things that
pertain to the entire LLVM Module. Many methods were in the wrong
category, such as type and value lowering.

This is a prerequisite commit for a local branch I am working on, which
needs to be able to call lowerValue() without the context of any
particular function or declaration.
2023-06-24 02:29:49 -07:00
kcbanner
9d66481e3d llvm: fixup elem_count argument of ZigLLVMCreateDebugArrayType to be i64
The signature is `getOrCreateSubrange(int64_t  Lo, int64_t  Count)`, so this updates the bindings to match.

This fixes a crash in `lowerDebugTypeImpl` when analyzing slices that have a length of 2^32 or
larger (up to `2^64 >> 3`, which still crashes, because above that the array size in bits overflows u64).
2023-06-23 14:53:17 -07:00
Jacob Young
96cdd51c14 Type: delete legacy allocation functions 2023-06-20 14:02:09 -04: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
Motiejus Jakštys
d41111d7ef mem: rename align*Generic to mem.align*
Anecdote 1: The generic version is way more popular than the non-generic
one in Zig codebase:

     git grep -w alignForward | wc -l
    56
     git grep -w alignForwardGeneric | wc -l
    149

     git grep -w alignBackward | wc -l
    6
     git grep -w alignBackwardGeneric | wc -l
    15

Anecdote 2: In my project (turbonss) that does much arithmetic and
alignment I exclusively use the Generic functions.

Anecdote 3: we used only the Generic versions in the Macho Man's linker
workshop.
2023-06-17 12:49:13 -07:00
Jacob Young
d37ebfcf23 InternPool: avoid as many slices pointing to string_bytes as possible
These are frequently invalidated whenever a string is interned, so avoid
creating pointers to `string_bytes` wherever possible.  This is an
attempt to fix random CI failures.
2023-06-11 23:45:09 -07:00
Jacob Young
b9a4eae349 llvm: fix more name lifetimes
Hopefully this also fixes the non-reproducing CI failures.
2023-06-11 03:01:17 -07:00
Jacob Young
a01bc7776f llvm: fix name lifetime 2023-06-10 20:51:10 -07:00
Jacob Young
bc3b56f957 llvm: fix undefined pointer type 2023-06-10 20:47:59 -07:00
Andrew Kelley
69b7b91092 compiler: eliminate Decl.value_arena and Sema.perm_arena
The main motivation for this commit is eliminating Decl.value_arena.
Everything else is dominoes.

Decl.name used to be stored in the GPA, now it is stored in InternPool.
It ended up being simpler to migrate other strings to be interned as
well, such as struct field names, union field names, and a few others.
This ended up requiring a big diff, sorry about that. But the changes
are pretty nice, we finally start to take advantage of InternPool's
existence.

global_error_set and error_name_list are simplified. Now it is a single
ArrayHashMap(NullTerminatedString, void) and the index is the error tag
value.

Module.tmp_hack_arena is re-introduced (it was removed in
eeff407941560ce8eb5b737b2436dfa93cfd3a0c) in order to deal with
comptime_args, optimized_order, and struct and union fields. After
structs and unions get moved into InternPool properly, tmp_hack_arena
can be deleted again.
2023-06-10 20:47:58 -07:00
Jacob Young
8299ddfe4f InternPool: fix more key lifetime issues
Reminder to look into deleting `get` and make keys less pointery and
more long lived.
2023-06-10 20:47:58 -07:00
Jacob Young
a3b3ac0ea4 llvm: fix lowering of lazy values
These really should not be making it to the backend, but that's a
problem for another time.
2023-06-10 20:47:58 -07:00
Jacob Young
828756ceeb InternPool: fix element pointer type computations 2023-06-10 20:47:58 -07:00
Andrew Kelley
bb526426e7 InternPool: remove memoized_decl
This is neither a type nor a value. Simplifies `addStrLit` as well as
the many places that switch on `InternPool.Key`.

This is a partial revert of bec29b9e498e08202679aa29a45dab2a06a69a1e.
2023-06-10 20:47:58 -07:00
mlugg
a0d4ef0acf InternPool: add representation for value of empty enums and unions
This is a bit odd, because this value doesn't actually exist:
see #15909. This gets all the empty enum/union behavior tests passing.

Also adds an assertion to `Sema.analyzeBodyInner` which would have
helped figure out the issue here much more quickly.
2023-06-10 20:47:57 -07:00
Andrew Kelley
82f6f164a1 InternPool: improve hashing performance
Key.PtrType is now an extern struct so that hashing it can be done by
reinterpreting bytes directly. It also uses the same representation for
type_pointer Tag encoding and the Key. Accessing pointer attributes now
requires packed struct access, however, many operations are now a copy
of a u32 rather than several independent fields.

This function moves the top two most used Key variants - pointer types
and pointer values - to use a single-shot hash function that branches
for small keys instead of calling memcpy.

As a result, perf against merge-base went from 1.17x ± 0.04 slower to
1.12x ± 0.04 slower. After the pointer value hashing was changed, total
CPU instructions spent in memcpy went from 4.40% to 4.08%, and after
additionally improving pointer type hashing, it further decreased to
3.72%.
2023-06-10 20:47:57 -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
3269256965 behavior: fix more compiler crashes 2023-06-10 20:47:56 -07:00
Jacob Young
3064d2aa7b behavior: additional llvm fixes 2023-06-10 20:47:56 -07:00
Jacob Young
3b6ca1d35b Module: move memoized data to the intern pool
This avoids memory management bugs with the previous implementation.
2023-06-10 20:47:56 -07:00
Jacob Young
d40b83de45 behavior: pass more tests on llvm again 2023-06-10 20:47:56 -07:00
Jacob Young
2d5bc01469 behavior: get more test cases passing with llvm 2023-06-10 20:47:56 -07:00
Jacob Young
9cd0ca9f48 Module: rename functions to make ownership checks explicit
This makes the difference between `decl.getOwnedFunction` and
`decl.val.getFunction` more clear when reading the code.
2023-06-10 20:47:55 -07:00
Andrew Kelley
ace5a5e3cc llvm: simplify control flow lowering structs 2023-06-10 20:47:55 -07:00
Jacob Young
abded5cbb0 TypedValue: implement more prints 2023-06-10 20:47:55 -07:00
Jacob Young
f2c716187c InternPool: fix more crashes 2023-06-10 20:47:55 -07:00
Andrew Kelley
66c4396854 AIR: eliminate the values array 2023-06-10 20:47:55 -07:00
Jacob Young
9afa974183 InternPool: fix enough crashes to run build-obj on a simple program 2023-06-10 20:47:55 -07:00
Jacob Young
9a738c0be5 Module: intern the values of decls when they are marked alive
I'm not sure if this is the right place for this to happen, and
it should become obsolete when comptime mutation is rewritten
and the remaining legacy value tags are remove, so keeping this
as a separate revertable commit.
2023-06-10 20:47:55 -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
72e4ea3821 InternPool: fix crashes up to in progress comptime mutation 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
Jacob Young
6e0de1d116 InternPool: port most of value tags 2023-06-10 20:47:54 -07:00
Jacob Young
484c3e8cbc llvm: fix incorrect slice lowering 2023-06-10 20:47:54 -07:00
Jacob Young
a7c3ca3531 InternPool: add lldb pretty printing for indices 2023-06-10 20:47:54 -07:00