120 Commits

Author SHA1 Message Date
Luuk de Gram
2c40b37f79 wasm: Implement @ctz for bitsize <= 64
Implements the `ctz` AIR instruction for integers with bitsize <= 64.
When the bitsize of the integer does not match the bitsize of a wasm type,
we first XOR the value with the value of (1<<bitsize) to set the right bits
and ensure we will only count the trailing zeroes of the integer with the correct bitsize.
2022-04-02 21:54:01 +02:00
Luuk de Gram
bd27fe2bf5 wasm: Implement @clz
Implements the `clz` AIR instruction for integers with bitsize <= 64.
When the bitsize of the integer is not the same as wasm's bitsize,
we substract the difference in bits as those will always be 0 for the integer, but should
not be counted towards the end result. We also wrap the result to ensure it fits
in the result type as documented in the language reference.
2022-04-02 21:54:01 +02:00
Luuk de Gram
5ba03369ee wasm: Implement @mulAdd for f32, f64
This implements the `mul_add` AIR instruction for floats of bitsize 32 and 64.
f16's will require us being able to extend and truncate f16's to correctly
store and load them without losing the accuracy.
2022-04-02 21:54:01 +02:00
Luuk de Gram
219fa192c6 wasm: Implement @maximum & @minimum
This implements the `max` and `min` AIR instructions by checking
whether LHS is great/lesser than RHS. If that's the case, we assign
LHS to the result, otherwise assign RHS to it instead.
2022-04-02 21:54:01 +02:00
Andrew Kelley
c21f046a8b Sema: enhance is_non_err to be comptime more often
* Sema: store the precomputed monomorphed_funcs hash inside Module.Fn.
   This is important because it may be accessed when resizing monomorphed_funcs
   while this Fn has already been added to the set, but does not have the
   owner_decl, comptime_args, or other fields populated yet.
 * Sema: in `analyzeIsNonErr`, take advantage of the AIR tag being
   `wrap_errunion_payload` to infer that `is_non_err` is comptime true
   without performing any error set resolution.
   - Also add some code to check for empty inferred error sets in this
     function. If necessary we do resolve the inferred error set.
 * Sema: queue full type resolution of payload type when
   `wrap_errunion_payload` AIR instruction is emitted. This ensures the
   backend may check the alignment of it.
 * Sema: resolveTypeFully now additionally resolves comptime-only
   status.

closes #11306
2022-03-30 00:47:55 -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
Luuk de Gram
3114faddd8
wasm: Implement overflow arithmetic
This implements the overflow arithmetic for unsigned and signed integers.
Meaning the following instructions:
- @addWithOverflow
- @subWithOverflow
- @shlWithOverflow
- @mulWithOverflow
2022-03-27 19:00:49 +02:00
Luuk de Gram
97448e4d5f wasm: Only generate import when referenced
Rather than creating an import for externs on updateDecl, we now
generate them when they're referenced. This is required so using @TypeOf(extern_fn())
will not emit the import into the binary (causing an incorrect function type index
as it won't be fully analyzed).
2022-03-26 21:20:29 +01:00
John Schmidt
f47db0a0db sema: use pl_op for @select 2022-03-25 16:13:54 +01:00
John Schmidt
12d5efcbe6 stage2: implement @select 2022-03-25 16:13:54 +01:00
Andrew Kelley
7378ce67da Sema: introduce a type resolution queue
That happens after a function body is analyzed. This prevents circular
dependency compile errors and yet a way to mark types that need to be
fully resolved before a given function is sent to the codegen backend.
2022-03-23 18:45:51 -07:00
Luuk de Gram
60676a0ba5
wasm: Implement more instructions
Implements the following instructions:
 - int_to_float
 - ptr_slice_len_ptr
 - ptr_slice_ptr_ptr
 - unwrap_errunion_payload_ptr
 - unwrap_errunion_err_ptr
2022-03-23 21:40:33 +01:00
Luuk de Gram
685f05b562
wasm: Implement opt_payload_ptr
Implements lowering constants for pointers of value 'opt_payload_ptr'.
The offset is calculated by determining the abi size of the full type and
then substracting the payload size.
2022-03-23 21:40:33 +01:00
Luuk de Gram
a9a629f89a
wasm: Fix switching on errors
Error sets contain the entire global error set.
Users are often switching on specific errors only present within that operand.
This means that cases are almost always sparse and not contiguous.
For this reason, we will instead emit the default case for error values not present in
that specific operand error set. This is fine as those cases will never be hit,
as prevented by the type system.

By still allowing jump tables for those cases, rather than if-else chains, we save runtime cost
as well as binary size.
2022-03-23 21:40:32 +01:00
Luuk de Gram
49051c0651
wasm: Implement @errorName
This implements the `error_name` instruction, which is emit for runtime `@errorName` callsites.

The implementation works by creating 2 symbols and corresponding atoms.
The initial symbol contains a table which each element consisting of a slice where the ptr field
points towards the error name, and the len field contains the error name length without the sentinel.

The secondary symbol contains a list of all error names from the global error set.

During the error_name instruction, we first get a pointer to the first symbol.
Then based on the operand we perform pointer arithmetic, to get the correct index into this table.
e.g. error index 2 = ptr + (2 * ptr size). The result of this will be stored in a local
and then returned as instruction result.

During `flush()` we populate the error names table by looping over the global error set
and creating a relocation for each error name. This relocation is appended to the table symbol.
Then finally, this name is written to the names list itself.

Finally, both symbols' atom are allocated within the rest of the binary.
When no error name is referenced, the `error_name_symbol` is never set, and therefore
no error name table will be emit into the final binary.
2022-03-23 21:40:32 +01:00
Andrew Kelley
593130ce0a stage2: lazy @alignOf
Add a `target` parameter to every function that deals with Type and
Value.
2022-03-22 15:45:58 -07:00
Luuk de Gram
be579d4797 wasm: Implement @popCount 2022-03-21 22:01:34 -04:00
William Sengir
0f48307041 stage2: add AIR instruction cmp_vector
The existing `cmp_*` instructions get their result type from `lhs`, but
vector comparison will always return a vector of bools with only the
length derived from its operands. This necessitates the creation of a
new AIR instruction.
2022-03-21 16:54:19 -07:00
Andrew Kelley
1bd595ceea
Merge pull request #11233 from Luukdegram/wasm-tests
stage2: wasm - union_init and passing tests
2022-03-19 19:41:55 -04:00
Luuk de Gram
56590218c5
wasm: All union/tuple/array tests passing
This implements improvements/fixes to get all the union, tuple, and array behavior tests passing.
Previously, we lowered parent pointers for field_ptr and element_ptr incompletely. This has now
been improved to recursively lower such pointer.

Also a fix was done to `generateSymbol` when checking a container's layout.
Previously it was assumed to always be a struct. However, the type can also be a tuple, and therefore
panicking. Updating to ask a type's container layout instead allows us to keep a singular branch for both cases.
2022-03-19 20:56:04 +01:00
Luuk de Gram
2041176c5e
wasm: Implement union_init instruction
Implements the `@unionInit` builtin instruction.
2022-03-19 20:56:03 +01:00
Veikka Tuominen
a8520fbd0f stage2: add dbg_block_{begin,end} instruction 2022-03-19 11:20:38 +02:00
Andrew Kelley
76b382072a
Merge pull request #11200 from Luukdegram/wasm-memcpy
stage2: wasm - Implement memcpy instruction
2022-03-17 18:25:15 -07:00
Andrew Kelley
7233a3324a stage2: implement @reduce
Notably, Value.eql and Value.hash are improved to treat NaN as equal to
itself, so that Type/Value can be hash map keys. Likewise float hashing
normalizes the float value before computing the hash.
2022-03-17 17:24:35 -07:00
Luuk de Gram
215a22541c
wasm: Improve memset implementation
When the length is comptime-known, we perform an inline loop instead of emitting
a runtime loop into the binary.

This also allows us to easily write 'undefined' to aggregate types.
We now do this when we set the error tag of an error union where the payload will be set to undefined.
2022-03-17 20:41:26 +01:00
Luuk de Gram
eafdc5562f
wasm: Implement 'memcpy' instruction
This implements the `memcpy` instruction and also updates the inline memcpy calls
to make use of the same implementation. We use the fast-loop when the length is comptime known,
and use a runtime loop when the length is runtime known.
We also perform feature-dection to emit a simply wasm memory.copy instruction when the feature
'bulk-memory' is enabled. (off by default).
2022-03-17 20:41:23 +01:00
Veikka Tuominen
d83a26f068 stage2 llvm: keep track of inlined functions 2022-03-16 10:53:41 +02:00
Veikka Tuominen
0343811836 Sema: emit dbg_func around inline calls 2022-03-16 09:34:26 +02:00
Andrew Kelley
0bc9635490 stage2: add debug info for locals in the LLVM backend
Adds 2 new AIR instructions:
 * dbg_var_ptr
 * dbg_var_val

Sema no longer emits dbg_stmt AIR instructions when strip=true.

LLVM backend: fixed lowerPtrToVoid when calling ptrAlignment on
the element type is problematic.

LLVM backend: fixed alloca instructions improperly getting debug
location annotated, causing chaotic debug info behavior.

zig_llvm.cpp: fixed incorrect bindings for a function that should use
unsigned integers for line and column.

A bunch of C test cases regressed because the new dbg_var AIR
instructions caused their operands to be alive, exposing latent bugs.
Mostly it's just a problem that the C backend lowers mutable
and const slices to the same C type, so we need to represent that in the
C backend instead of printing two duplicate typedefs.
2022-03-13 03:41:31 -04:00
Veikka Tuominen
cba68090a6 stage2: implement @shuffle at runtime 2022-03-11 13:12:32 +02:00
Andrew Kelley
078037ab9b stage2: passing threadlocal tests for x86_64-linux
* use the real start code for LLVM backend with x86_64-linux
   - there is still a check for zig_backend after initializing the TLS
     area to skip some stuff.
 * introduce new AIR instructions and implement them for the LLVM
   backend. They are the same as `call` except with a modifier.
   - call_always_tail
   - call_never_tail
   - call_never_inline
 * LLVM backend calls hasRuntimeBitsIgnoringComptime in more places to
   avoid unnecessarily depending on comptimeOnly being resolved for some
   types.
 * LLVM backend: remove duplicate code for setting linkage and value
   name. The canonical place for this is in `updateDeclExports`.
 * LLVM backend: do some assembly template massaging to make `%%`
   rendered as `%`. More hacks will be needed to make inline assembly
   catch up with stage1.
2022-03-11 00:04:42 -07:00
Luuk de Gram
3ea113e008 wasm: Implement field_parent_ptr 2022-03-09 13:53:10 -07:00
Luuk de Gram
f931c0638d wasm: Implement errunion_payload_ptr_set
This also fixes `ret_ptr` where the pointee type is zero-sized.
2022-03-09 13:53:10 -07:00
Luuk de Gram
d01bfa032d wasm: Preliminary fptrunc support
This implements the initial fptrunc instruction. For all other floating-point truncating,
a call to compiler-rt is required. (This also updates fpext to emit the same error).
2022-03-09 13:53:10 -07:00
Luuk de Gram
684b81f366 wasm: Implement fpext
This implements initial support for floating-point promotion for bitsizes <= 64
2022-03-09 13:53:10 -07:00
Luuk de Gram
557f396f61 wasm: Improve switch implementation
- Implement switching over booleans and pointers.
- Fix sparse-detection where the lowest value was never truly set
as it started at a non-zero number and the case was > 50.
- Fix indexing the jump table by ensuring it starts indexing from 0.
2022-03-09 13:53:10 -07:00
John Schmidt
6637335981 stage2: implement @mulAdd for scalar floats 2022-03-06 15:36:56 -07:00
Luuk de Gram
13fca53b92
wasm: Unify function generation
Like decl code generation, also unify the wasm backend and the wasm linker to call into
the general purpose `codegen.zig` to generate the code for a function.
2022-03-06 19:38:53 +01:00
Luuk de Gram
2faba4092a
wasm: Remove old DeclGen/genTypedValue 2022-03-06 19:38:53 +01:00
Luuk de Gram
5a45fe2dba
wasm: Call generateSymbol for updateDecl
To unify the wasm backend with the other backends, we will now call `generateSymbol` to
lower a Decl into bytes. This means we also have to change some function signatures
to comply with the linker interface.

Since the general purpose generateSymbol is less featureful than wasm's, some tests are
temporarily disabled.
2022-03-06 19:38:50 +01:00
Andrew Kelley
e532b0c0b5 stage2: cleanups to wasm memory intrinsics
* AIR: use pl_op instead of ty_pl for wasm_memory_size. No need to
   store the type because the type is always `u32`.
 * AstGen: use coerced_ty for `@wasmMemorySize` and `@wasmMemoryGrow`
   and do the coercions in Sema.
 * Sema: use more accurate source locations for errors.
 * Provide more information in the compiler error message.
 * Codegen: use liveness data to avoid lowering unused
   `@wasmMemorySize`.
 * LLVM backend: add implementation
   - I wasn't able to test it because we are hitting a linker error for
     `-target wasm32-wasi -fLLVM`.
 * C backend: use `zig_unimplemented()` instead of silently doing wrong
   behavior for these builtins.
 * behavior tests: branch only on stage2_arch for inclusion of the
   wasm.zig file. We would change it to `builtin.cpu.arch` but that is
   causing a compiler crash on some backends.
2022-03-03 18:31:55 -07:00
Luuk de Gram
7fd32de018 cbe: Implement wasm builtins
This implements the wasm builtins by lowering to builtins that are supported by c-compilers.
In this case: Clang.

This also simplifies the `AIR` instruction as it now uses the payload field of `ty_pl` and `pl_op`
directly to store the index argument rather than storing it inside Extra. This saves us 4 bytes
per builtin call.
2022-03-03 16:33:46 -07:00
Luuk de Gram
43cb19ea4d wasm: Implement @wasmMemoryGrow builtin
Similarly to the other wasm builtin, this implements the grow variation where the memory
index is a comptime known value. The operand as well as the result are runtime values.
This also verifies during semantic analysis the target we're building for is wasm, or else
emits a compilation error. This means that other backends do not have to handle this AIR instruction,
other than the wasm and LLVM backends.
2022-03-03 16:33:46 -07:00
Luuk de Gram
ec4c30ae48 wasm: Implement @wasmMemorySize() builtin
This implements the `wasmMemorySize` builtin, in Sema and the Wasm backend.
The Stage2 implementation differs from stage1 in the way that `index` must be a comptime value.
The stage1 variant is incorrect, as the index is part of the instruction encoding, and therefore,
cannot be a runtime value.
2022-03-03 16:33:46 -07:00
Andrew Kelley
d5100dc815 stage2: fix frame_address AIR instruction
Various places were assuming different union tags. Now it is
consistently a no-op instruction, just like the similar
instruction ret_addr.
2022-02-28 13:38:33 -07:00
Veikka Tuominen
90bce11f62 stage2: implement @frameAddress 2022-02-28 13:09:14 -07:00
Andrew Kelley
2687b8f7f4 stage2: implement @unionInit
The ZIR instruction `union_init_ptr` is renamed to `union_init`.
I made it always use by-value semantics for now, not taking the time to
invest in result location semantics, in case we decide to change the
rules for unions. This way is much simpler.

There is a new AIR instruction: union_init. This is for a comptime known
tag, runtime-known field value.
vector_init is renamed to aggregate_init, which solves a TODO comment.
2022-02-26 20:59:36 -07:00
Luuk de Gram
0147eb9b58 wasm: Fix error union's size/alignment
Previously error unions were packed in memory. Now each 'field' is correctly
aligned to the error union's alignment.
2022-02-25 09:33:15 +01:00
Luuk de Gram
f4adb53bcf wasm: Refactor lowerUnnamedConst
Rather than ping ponging between codegen and the linker to generate the symbols/atoms
for a local constant and its relocations. We now create all neccesary objects within the linker.

This simplifies the code as we can now simply call `lowerUnnamedConst` from anywhere in codegen,
allowing us to further improve lowering constants into .rodata so we do not have to sacrifice
lowering certain types such as decl_ref's where its type is a slice.
2022-02-25 09:33:15 +01:00
Veikka Tuominen
b034c45b2b stage2: implement fieldParentPtr 2022-02-24 19:48:34 +02:00