This updates the C backend to use proper array types.
In order to do that, this commit also:
- fixes up elem_ptr and field_ptr handling
- adds `renderTypecast` (renders in C typecast format, e.g. "int* [10]")
- adds a bit special handling for undefined pointers, which is necessary
to support slice/elem_ptr to undefined decls
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.
`ExternFn` will contain a maybe-lib-name if it was defined with
the `extern` keyword like so
```zig
extern "c" fn write(usize, usize, usize) usize;
```
`lib_name` will live as long as `ExternFn` decl does.
rather than unconditionally prepending double underscore to all
identifiers. Also, use the prefix `zig_e_` instead of `__`. Also, avoid
triggering this escaping when rendering an identifier and there has
already been a prefix printed.
AstGen:
* rename the known_has_bits flag to known_non_opv to make it better
reflect what it actually means.
* add a known_comptime_only flag.
* make the flags take advantage of identifiers of primitives and the
fact that zig has no shadowing.
* correct the known_non_opv flag for function bodies.
Sema:
* Rename `hasCodeGenBits` to `hasRuntimeBits` to better reflect what it
does.
- This function got a bit more complicated in this commit because of
the duality of function bodies: on one hand they have runtime bits,
but on the other hand they require being comptime known.
* WipAnonDecl now takes a LazySrcDecl parameter and performs the type
resolutions that it needs during finish().
* Implement comptime `@ptrToInt`.
Codegen:
* Improved handling of lowering decl_ref; make it work for
comptime-known ptr-to-int values.
- This same change had to be made many different times; perhaps we
should look into merging the implementations of `genTypedValue`
across x86, arm, aarch64, and riscv.
There are some differences vs. the union encoding in the LLVM backend:
- Tagged unions with a 0-bit payload do not become their tag type. Instead,
they are a struct with an empty `union` as their payload field.
- We do not order the `payload`/`tag` storage based on their alignment
There are some restrictions here.
- We either need C11 or a compiler that supports the aligned attribute
- We cannot provide align less than the type's natural C alignment.
This reverts commit d48e4245b68bf25c7f41804a5012ac157a5ee546.
I have no idea why this is failing Drone CI, but in a branch, reverting
this commit solved the problem.
It is the job of codegen backends to mark Decls that are referenced as
alive so that the frontend does not sweep them with the garbage. This
commit unifies the code between the backends with an added method on
Decl.
The implementation is more complete than before, switching on the Decl
val tag and recursing into sub-values.
As a result, two more array tests are passing.
Introduce `validate_array_init_comptime`, similar to
`validate_struct_init_comptime` introduced in
713d2a9b3883942491b40738245232680877cc66.
`zirValidateArrayInit` is improved to detect comptime array literals and
emit AIR accordingly. This code is very similar to the changes
introduced in that same commit for `zirValidateStructInit`.
The C backend needed some improvements to continue passing the same set
of tests:
* `resolveInst` for arrays now will add a local `static const` with the
array value and so then `elem_val` instructions reference that local.
It memoizes accesses using `value_map`, which is changed to use
`Air.Inst.Ref` as the key rather than `Air.Inst.Index`.
* This required a mechanism for writing to a "header" which is lines
that appear at the beginning of a function body, before everything
else.
* dbg_stmt output comments rather than `#line` directives.
TODO comment reproduced here:
We need to re-evaluate whether to emit these or not. If we naively emit
these directives, the output file will report bogus line numbers because
every newline after the #line directive adds one to the line.
We also don't print the filename yet, so the output is strictly unhelpful.
If we wanted to go this route, we would need to go all the way and not output
newlines until the next dbg_stmt occurs.
Perhaps an additional compilation option is in order?
`Value.elemValue` is improved to support `elem_ptr` values.
AIR:
* `array_elem_val` is now allowed to be used with a vector as the array
type.
* New instructions: splat, vector_init
AstGen:
* The splat ZIR instruction uses coerced_ty for the ResultLoc, avoiding
an unnecessary `as` instruction, since the coercion will be performed
in Sema.
* Builtins that accept vectors now ignore the type parameter. Comment
from this commit reproduced here:
The accepted proposal #6835 tells us to remove the type parameter from
these builtins. To stay source-compatible with stage1, we still observe
the parameter here, but we do not encode it into the ZIR. To implement
this proposal in stage2, only AstGen code will need to be changed.
Sema:
* `clz` and `ctz` ZIR instructions are now handled by the same function
which accept AIR tag and comptime eval function pointer to
differentiate.
* `@typeInfo` for vectors is implemented.
* `@splat` is implemented. It takes advantage of `Value.Tag.repeated` 😎
* `elemValue` is implemented for vectors, when the index is a scalar.
Handling a vector index is still TODO.
* Element-wise coercion is implemented for vectors. It could probably
be optimized a bit, but it is at least complete & correct.
* `Type.intInfo` supports vectors, returning int info for the element.
* `Value.ctz` initial implementation. Needs work.
* `Value.eql` is implemented for arrays and vectors.
LLVM backend:
* Implement vector support when lowering `array_elem_val`.
* Implement vector support when lowering `ctz` and `clz`.
* Implement `splat` and `vector_init`.
const locals now detect if the value ends up being comptime known. In
such case, it replaces the runtime AIR instructions with a decl_ref
const.
In the backends, some more sophisticated logic for marking decls as
alive was needed to prevent Decls incorrectly being garbage collected
that were indirectly referenced in such manner.
Effectively a small continuation of #10152
This allows the for.zig behavior tests to pass. Unfortunately to fully test everything I had to move a lot of behavior tests from array.zig; most of them now pass (sorry @rainbowbismuth!)
I'm also conflicted on how I store constants into arrays because it's kind of stupid; array's can't be re-initialized using the same syntax, so instead of initializing each element, a new array is made which is copied into the destination. This also required that renderValue can't emit string literals for byte arrays given that they need to always have an extra byte for the NULL terminator, meaning that strings are no longer grep-able in the output.
* fix initialisation of void* fields of structs (initialises to 0xaa.. rather than {})
* don't generate struct fields when the field type does not have codegen bits
* in airAlloc generate a void* literal if the element type does not have codegen bits
Introduced a new AIR instruction: `tag_name`. Reasons to do this
instead of lowering it in Sema to a switch, function call, array
lookup, or if-else tower:
* Sema is a bottleneck; do less work in Sema whenever possible.
* If any optimization passes run, and the operand to becomes
comptime-known, then it could change to have a comptime result
value instead of lowering to a function or array or something which
would then have to be garbage-collected.
* Backends may want to choose to use a function and a switch branch,
or they may want to use a different strategy.
Codegen for `@tagName` is implemented for the LLVM backend but not any
others yet.
Introduced some new `Type` tags:
* `const_slice_u8_sentinel_0`
* `manyptr_const_u8_sentinel_0`
The motivation for this was to make typeof() on the tag_name AIR
instruction non-allocating.
A bunch more enum tests are passing now.
This allows the inferred error set of comptime and inline invocations to be
resolved separately from the inferred error set of the runtime version or other
comptime/inline invocations.
-airLoad and airStore now properly report an error if they are used with an array, instead of having the C compiler emit a vague error
-airStoreUndefined now works with array types
-structFieldPtr now works with array types, allowing generics' tests to pass