112 Commits

Author SHA1 Message Date
Cody Tapscott
d060cbbec7 stage2: Keep error return traces alive when storing to const
This change extends the "lifetime" of the error return trace associated
with an error to continue throughout the block of a `const` variable
that it is assigned to.

This is necessary to support patterns like this one in test_runner.zig:
```zig
const result = foo();
if (result) |_| {
    // ... success logic
} else |err| {
    // `foo()` should be included in the error trace here
    return error.TestFailed;
}
```

To make this happen, the majority of the error return trace popping logic
needed to move into Sema, since `const x = foo();` cannot be examined
syntactically to determine whether it modifies the error return trace. We
also have to make sure not to delete pertinent block information before it
makes it to Sema, so that Sema can pop/restore around blocks correctly.

* Why do this only for `const` and not `var`? *

There is room to relax things for `var`, but only a little bit. We could
do the same thing we do for const and keep the error trace alive for the
remainder of the block where the *assignment* happens. Any wider scope
would violate the stack discipline for traces, so it's not viable.

In the end, I decided the most consistent behavior for the user is just
to kill all error return traces assigned to a mutable `var`.
2022-10-21 12:40:29 -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
Andrew Kelley
0a89624d59 stage2: support being built in ReleaseSafe mode 2022-09-13 18:08:59 -07: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
Andrew Kelley
40f8f0134f Sema: enhance div_trunc, div_exact, div_floor
* No longer emit div_exact AIR instruction that can produce a
   remainder, invoking undefined behavior.
 * div_trunc, div_exact, div_floor are extracted from analyzeArithmetic
   and directly handled similarly to div_trunc, integrating them with
   integer overflow safety checking.
 * Also they no longer emit divide-by-zero safety checking when RHS
   is comptime known to be non-zero.
2022-07-29 02:35:06 -07: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
6d3586e0ed explicit "_ptr" variants of ZIR try instruction
* Introduce "_ptr" variants of ZIR try instruction to disallow constructs
   such as `try` on a pointer value instead of an error union value.
 * Disable the "_inline" variants of the ZIR try instruction for now because
   we are out of ZIR tags. I will free up some space in an independent commit.
 * AstGen: fix tryExpr calling rvalue() on ResultLoc.ref
2022-06-05 10:37:08 +02: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
83f69af971 stage2: implement runtime array multiplication
Additionally:

 * Sema: fix array cat/mul not setting the sentinel value
   - This required an LLVM backend enhancement to the handling of the
     AIR instruction aggregate_init that likely needs to be
     propagated to the other backends.
 * Sema: report integer overflow of array concatenation in a proper
   compile error instead of crashing.
 * Sema: fix not using proper pointer address space for array cat/mul
2022-05-25 22:33:48 -07: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
65389dc280 stage2: improve inline asm stage1 compatibility
* outputs can have names and be referenced with template replacements
   the same as inputs.
 * fix print_air.zig not decoding correctly.
 * LLVM backend: use a table for template names for simplicity
2022-05-02 22:14:17 -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
Veikka Tuominen
75c2cff40e stage2: handle assembly input names 2022-03-31 01:33:28 -04: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
1803167db2
AIR: change signature of overflow arithmetic instructions
add_with_overflow and similar functions now have the ty_pl data
attached. The Payload will now be a binary operation and the inst is
expected to return a tuple consisting of the destination integer type
and an overflow bit (u1).

Co-authored-by: Jan Philipp Hafer <jan.hafer@rwth-aachen.de>
2022-03-26 17:21:39 +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
William Sengir
2d8fef5680 stage2: make bool binop AIR return types based on operand type
This allows vector-of-bools operands to return a vector-of-bools.
2022-03-21 16:54:19 -07: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
Veikka Tuominen
a8520fbd0f stage2: add dbg_block_{begin,end} instruction 2022-03-19 11:20:38 +02: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
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
Andrew Kelley
71b8760d3b stage2: rework @mulAdd
* mul_add AIR instruction: use `pl_op` instead of `ty_pl`. The type is
   always the same as the operand; no need to waste bytes redundantly
   storing the type.
 * AstGen: use coerced_ty for all the operands except for one which we
   use to communicate the type.
 * Sema: use the correct source location for requireRuntimeBlock in
   handling of `@mulAdd`.
 * native backends: handle liveness even for the functions that are
   TODO.
 * C backend: implement `@mulAdd`. It lowers to libc calls.
 * LLVM backend: make `@mulAdd` handle all float types.
   - improved fptrunc and fpext to handle f80 with compiler-rt calls.
 * Value.mulAdd: handle all float types and use the `@mulAdd` builtin.
 * behavior tests: revert the changes to testing `@mulAdd`. These
   changes broke the test coverage, making it only tested at
   compile-time.

Improved f80 support:
 * std.math.fma handles f80
 * move fma functions from freestanding libc to compiler-rt
   - add __fmax and fmal
   - make __fmax and fmaq only exported when they don't alias fmal.
   - make their linkage weak just like the rest of compiler-rt symbols.
 * removed `longDoubleIsF128` and replaced it with `longDoubleIs` which
   takes a type as a parameter. The implementation is now more accurate
   and handles more targets. Similarly, in stage2 the function
   CTypes.sizeInBits is more accurate for long double for more targets.
2022-03-06 16:11:39 -07:00
John Schmidt
6637335981 stage2: implement @mulAdd for scalar floats 2022-03-06 15:36:56 -07: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
Veikka Tuominen
b034c45b2b stage2: implement fieldParentPtr 2022-02-24 19:48:34 +02:00
Veikka Tuominen
27c63bf433 stage2: implement errunion_payload_ptr_set 2022-02-19 20:48:00 +02:00
Andrew Kelley
2e1c16d649
Merge pull request #10924 from ziglang/air-independence-day
AIR independence day
2022-02-19 02:57:48 -05:00
Andrew Kelley
4e1e5ab622 stage2: make AIR not reference ZIR for inline assembly
Instead it stores all the information it needs to into AIR.

closes #10784
2022-02-18 19:41:32 -07:00
Andrew Kelley
32edb9b55d stage2: eliminate ZIR arg instruction references to ZIR
Prior to this commit, the AIR arg instruction kept a reference to a ZIR
string index for the corresponding parameter name. This is used by DWARF
emitting code. However, this is a design flaw because we want AIR
objects to be independent from ZIR.

This commit saves the parameter names into memory managed by
`Module.Fn`. This is sub-optimal because we should be able to get the
parameter names from the ZIR for a function without having them
redundantly stored along with `Fn` memory. However the current way that
ZIR param instructions are encoded does not support this case. They
appear in the same ZIR body as the function instruction, just before it.
Instead, they should be embedded within the function instruction, which
will allow this TODO to be solved. That improvement is too big for this
commit, however.

After this there is one last dependency to untangle, which is for inline
assembly. The issue for that is #10784.
2022-02-18 16:56:12 -07:00
Cody Tapscott
ef417f19e1 stage2: Implement @bitReverse and @byteSwap
This change implements the above built-ins for Sema and the LLVM
backend. Other backends have had placeholders added for lowering.
2022-02-18 14:28:32 -07:00
John Schmidt
7f0cf395aa stage2: implement all builtin floatops for f{16,32,64}
- Merge `floatop.zig` and `floatop_stage1.zig` since most tests now pass
  on stage2.
- Add more behavior tests for a bunch of functions.
2022-02-09 20:29:41 -05:00
Andrew Kelley
97019bc56d Sema: handle inferred error set tail call
When Sema sees a store_node instruction, it now checks for
the possibility of this pattern:
  %a = ret_ptr
  %b = store(%a, %c)
Where %c is an error union. In such case we need to add to the
current function's inferred error set, if any.

Coercion from error union to error union will be handled ideally if the
operand is comptime known. In such case it does the appropriate
unwrapping, then wraps again.

In the future, coercion from error union to error union should do the
same thing for a runtime value; emitting a runtime branch to check if
the value is an error or not.

`Value.arrayLen` for structs returns the number of fields. This is so
that Liveness can use it for the `vector_init` instruction (soon to be
renamed to `aggregate_init`).
2022-02-09 00:10:53 -07:00
John Schmidt
722d4a11bb stage2: implement @sqrt for f{16,32,64}
Support for f128, comptime_float, and c_longdouble require improvements
to compiler_rt and will implemented in a later PR. Some of the code in
this commit could be made more generic, for instance `llvm.airSqrt`
could probably be `llvm.airUnaryMath`, but let's cross that
bridge when we get to it.
2022-02-07 16:52:19 -07:00
Andrew Kelley
fb7060d3c2 stage2: implement shl_exact and shr_exact
These produce an undefined value when one bits are shifted out.

New AIR instruction: shr_exact.
2022-01-30 16:23:31 -07:00