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.
* AIR instruction vector_init gains the ability to init arrays and
tuples in addition to vectors. This will probably also gain the
ability to initialize structs and be renamed to `aggregate_init`.
* AstGen prefers to use an `anon_array_init` ZIR instruction for
local variables when the init expr is an array literal and there is
no type.
* push the arguments in reverse order
* add logic for pushing args of any abi size to stack - very similar to
`genSetStack` however, uses `.rsp` as the base register
* increment and decrement `.rsp` if we called a function with args on
the stack in `airCall`
* add logic for recovering args from the caller's stack in the callee
Due to the new structure of lowerConstant, we can now simplify the logic in a lot of situations.
- We no longer have to check the `WValue`'s tag to determine how to load/store a value.
- We can now provide simple memcopy's for aggregate types.
- Constants are now memoized, meaning we do no longer lower constants on each callsite.
In the behavior test listings, I had to move type_info.zig test import
to a section that did not include the x86 backend because it got to the
point where adding another test to the file, even if it was an empty
test that just returned immediately, caused a runtime failure when
executing the test binary.
Anyway, type info for opaques is implemented, and the declarations slice
is shared between it, enums, and unions.
Still TODO is the `data` field of a `Declaration`. I want to consider
removing it from the data returned from `@typeInfo` and introducing
`@declInfo` or similar for this data. This would avoid the complexity of
a lazy mechanism.
Instead use the standarized option for communicating the
zig compiler backend at comptime, which is `zig_backend`. This was
introduced in commit 1c24ef0d0b09a12a1fe98056f2fc04de78a82df3.
The ZIR instructions `switch_capture_else` and `switch_capture_ref` are
removed because they are not needed. Instead, the prong index is set to
max int for the special prong.
Else prong with error sets is not handled yet.
Adds a new behavior test because there was not a prior on to cover only
the capture value of else on a switch.
Previously, breaking from an outer block at comptime would result in
incorrect control flow. Now there is a mechanism, `error.ComptimeBreak`,
similar to `error.ComptimeReturn`, to send comptime control flow further
up the stack, to its matching block.
This commit also introduces a new log scope. To use it, pass
`--debug-log sema_zir` and you will see 1 line per ZIR instruction
semantically analyzed. This is useful when you want to understand what
comptime control flow is doing while debugging the compiler.
One more `switch` test case is passing.
* implement `genSetStack` for `ptr_stack_offset`
* handle `ptr_add`
* implement storing from register into pointer in register
* split alignment and array tests into those that pass on x86_64 and
those that do not
* pass more tests on x86_64
There is a mechanism to avoid redundant `as` ZIR instructions which is
to pass `ResultLoc.coerced_ty` instead of `ResultLoc.ty` when it is
known by AstGen that Sema will do the coercion.
This commit downgrades `coerced_ty` to `ty` when a result location
passes through an expression that branches, such as `if`, `switch`,
`while`, and `for`, causing the `as` ZIR instruction to be emitted.
This ensures that the type of a result location will be applied to, e.g.
a `comptime_int` on either side of a branch on a runtime condition.
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`.
- This implements the float_to_int AIR instruction.
- Lowering a decl_ref to a slice was previously assumed to contain a pointer
to a slice, rather than an array. This is now fixed, making `@src()` work as well.
- Some preliminary work on 128bit integers have been done to find out what needs to be done
to implement 128bit arithmetic.
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.
This allows stage2 to build more of compiler-rt.
I also changed `-%` to `-` for comptime ints in the div and mul
implementations of compiler-rt. This is clearer code and also happens to
work around a bug in stage2.
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.
* `Module.Union.getLayout`: fixes to support components of the union
being 0 bits.
* Implement `@typeInfo` for unions.
* Add missing calls to `resolveTypeFields`.
* Fix explicitly-provided union tag types passing a `Zir.Inst.Ref`
where an `Air.Inst.Ref` was expected. We don't have any type safety
for this; these typess are aliases.
* Fix explicitly-provided `union(enum)` tag Values allocated to the
wrong arena.
* reduce number of branches in zirCmpEq
* implement equality comparison for enums and unions
* fix coercion from union to its tag type resulting in the wrong type
* fix method calls of unions
* implement peer type resolution for unions, enums, and enum literals
* fix union tag type memory in the wrong arena
Comment from this commit reproduced here:
LLVM does not allow us to change the type of globals. So we must
create a new global with the correct type, copy all its attributes,
and then update all references to point to the new global,
delete the original, and rename the new one to the old one's name.
This is necessary because LLVM does not support const bitcasting
a struct with padding bytes, which is needed to lower a const union value
to LLVM, when a field other than the most-aligned is active. Instead,
we must lower to an unnamed struct, and pointer cast at usage sites
of the global. Such an unnamed struct is the cause of the global type
mismatch, because we don't have the LLVM type until the *value* is created,
whereas the global needs to be created based on the type alone, because
lowering the value may reference the global as a pointer.