The main purpose of this commit is to prepare to implement support for
callconv(), align(), linksection(), and addrspace() annotations on
generic functions where the provided expression depends on comptime
parameters (making the function generic).
It's a rather involved change, so this commit only makes the necessary
changes to AstGen without regressing any behavior, and a follow-up
commit can finish the task by making the enhancements to Sema.
By my quick estimation, the new encoding for functions is a negligible
improvement - along the lines of 0.005% fewer total ZIR bytes on
average. Still, it's nice that this commit, while adding more
data into ZIR, actually ends up reducing the storage size thanks to a
slightly more sophisticated encoding.
Zir.Inst.ExtendedFunc is renamed to Zir.Inst.FuncFancy to eliminate
confusion about it being an extended instruction (it used to be but is
no longer). The encoding for this instruction is completely reworked.
The encoding for Zir.Inst.Func is also changed slightly - when the
return type body length is 1, then only a Zir.Inst.Ref is provided; not
a full body.
linksection() and addrspace() are now communicated via func_fancy ZIR
instruction rather than as part of the corresponding decl. This allows
their expressions to observe comptime parameters.
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
This is needed because pointers to zero-bit types are not necessarily
comptime known, but when doing a load, only the element type having one
possible value is relevant.
* `?E` where E is an error set with only one field now lowers the same
as `bool`.
* Fix implementation of errUnionErrOffset and errUnionPayloadOffset to
properly compute the offset of each field. Also name them the same
as the corresponding LLVM functions and have the same function
signature, to avoid confusion. This fixes a bug where wasm was
passing the error union type instead of the payload type.
* Fix C backend handling of optionals with zero-bit payload types.
* C backend: separate out airOptionalPayload and airOptionalPayloadPtr
which reduces branching and cleans up control flow.
* Make Type.isNoReturn return true for error sets with no fields.
* Make `?error{}` have only one possible value (null).
* Sema: avoid unnecessary safety checks when an error set is empty.
* Sema: make zirErrorToInt handle comptime errors that are represented
as integers.
* Sema: make empty error sets properly integrate with
typeHasOnePossibleValue.
* Type: correct the ABI alignment and size of error unions which have
both zero-bit error set and zero-bit payload. The previous code did
not account for the fact that we still need to store a bit for
whether there is an error.
* LLVM: lower error unions possibly with the payload first or with the
error code first, depending on alignment. Previously it always put
the error code first and used a padding array.
* LLVM: lower functions which have an empty error set as the return
type the same as anyerror, so that they can be used where
fn()anyerror function pointers are expected. In such functions, Zig
will lower ret to returning zero instead of void.
As a result, one more behavior test is passing.
This is a temporary addition to stage2 in order to match stage1 behavior,
however the end-game once the lang spec is settled will be to use a global
InternPool for comptime memoized objects, making this behavior consistent
across all types, not only string literals. Or, we might decide to not
guarantee string literals to have equal comptime pointers, in which case
this commit can be reverted.
Motivation: the behavior test that is now passing.
The main change in this commit is introducing `Type.abiSizeAdvanced`,
`Value.Tag.lazy_size`, and adjusting `Sema.zirSizeOf` to take advantage
of these.
However, the bulk of lines changed in this commit ended up being moving
logic from value.zig and type.zig into Sema.zig. This logic had no
business being in Type/Value as it was only called from a Sema context,
and we need access to the Sema context for error reporting when a lazy
Value is resolved.
Also worth mentioning is that I bumped up the comptime `@floatToInt`
implementation from using f64 to f128.
`@call` allows specifying the modifier explicitly, however it can still
appear in a context that overrides the modifier. This commit adds flags
to the BuiltinCall ZIR encoding. Since we have unused bits I also threw
in the ensure_result_used mechanism.
I also deleted a behavior test that was checking for bound function
behavior where I think stage2 behavior is correct and stage1 behavior
is incorrect.
When handling the `negate` ZIR instruction, Zig now checks for a
comptime operand and handles it as a special case rather than lowering
it as `0 - x` so that the expression `-x` where `x` is a floating point
value known at compile-time, will get the negative zero bitwise
representation.
* Rename std.builtin.GlobalVisibility to std.builtin.SymbolVisibility
* Add missing compile error. From the LLVM language reference: "A
symbol with internal or private linkage must have default
visibility."
This improves the ABI alignment resolution code.
This commit fully enables the MachO linker code in stage3. Note,
however, that there are still miscompilations in stage3.
So far it's supported by the LLVM backend only. I recommend for the
other backends to wait for the resolution of #10761 before adding
support for this feature.
ZIR instructions updated: atomic_load, atomic_rmw, atomic_store, cmpxchg
These no longer construct a pointer type as the result location. This
solves a TODO that was preventing the pointer from possibly being
volatile, as well as properly handling allowzero and addrspace.
It also allows the pointer to be over-aligned, which may be needed
depending on the target. As a consequence, the element type needs to be
communicated in the ZIR. This is done by strategically making one of the
operands be ResultLoc.ty instead of ResultLoc.coerced_ty if possible, or
otherwise explicitly adding elem_type into the ZIR encoding, such as in
the case of atomic_load.
The pointer type of atomic operations is now checked in Sema by coercing
it to an expected pointer type, that maybe over-aligned according to
target requirements.
Together with the previous commit, Zig now has smaller alignment for
large integers, depending on the target, and yet still has type safety
for atomic operations that specially require higher alignment.
* 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
Instead of doing heterogeneous comparison at comptime. This makes the
following test pass (as it already does for stage1):
```zig
test {
const x: f64 = 12.34;
expect(x == 12.34);
}
```
There is already behavior test coverage for this, however, other bugs in
`std.fmt.parseFloat` are masking the failures.
From a language specification perspective, this makes sense because it
makes comptime comparisons with comptime_float work the same way they
work with runtime comparisons.
* Sema: Correctly determine whether array_cat lhs and rhs are single ptrs
Many-pointers are also not single-pointers and wouldn't be considered
here. This commit makes the conditions use the appropriately-named
isSinglePointer instead.
* Sema: Correctly obtain ArrayInfo for many-pointer concatenation
Many-pointers at comptime have a known size like slices and can be used
in array concatenation. This fixes a stage1 regression.
* test: Add comptime manyptr concatenation test
Co-authored-by: sin-ack <sin-ack@users.noreply.github.com>