This commit removes the `field_call_bind` and `field_call_bind_named` ZIR
instructions, replacing them with a `field_call` instruction which does the bind
and call in one.
`field_call_bind` is an unfortunate instruction. It's tied into one very
specific usage pattern - its result can only be used as a callee. This means
that it creates a value of a "pseudo-type" of sorts, `bound_fn` - this type used
to exist in Zig, but now we just hide it from the user and have AstGen ensure
it's only used in one way. This is quite silly - `Type` and `Value` should, as
much as possible, reflect real Zig types and values.
It makes sense to instead encode the `a.b()` syntax as its own ZIR instruction,
so that's what we do here. This commit introduces a new instruction,
`field_call`. It's like `call`, but rather than a callee ref, it contains a ref
to the object pointer (`&a` in `a.b()`) and the string field name (`b`). This
eliminates `bound_fn` from the language, and slightly decreases the size of
generated ZIR - stats below.
This commit does remove a few usages which used to be allowed:
- `@field(a, "b")()`
- `@call(.auto, a.b, .{})`
- `@call(.auto, @field(a, "b"), .{})`
These forms used to work just like `a.b()`, but are no longer allowed. I believe
this is the correct choice for a few reasons:
- `a.b()` is a purely *syntactic* form; for instance, `(a.b)()` is not valid.
This means it is *not* inconsistent to not allow it in these cases; the
special case here isn't "a field access as a callee", but rather this exact
syntactic form.
- The second argument to `@call` looks much more visually distinct from the
callee in standard call syntax. To me, this makes it seem strange for that
argument to not work like a normal expression in this context.
- A more practical argument: it's confusing! `@field` and `@call` are used in
very different contexts to standard function calls: the former normally hints
at some comptime machinery, and the latter that you want more precise control
over parts of a function call. In these contexts, you don't want implicit
arguments adding extra confusion: you want to be very explicit about what
you're doing.
Lastly, some stats. I mentioned before that this change slightly reduces the
size of ZIR - this is due to two instructions (`field_call_bind` then `call`)
being replaced with one (`field_call`). Here are some numbers:
+--------------+----------+----------+--------+
| File | Before | After | Change |
+--------------+----------+----------+--------+
| Sema.zig | 4.72M | 4.53M | -4% |
| AstGen.zig | 1.52M | 1.48M | -3% |
| hash_map.zig | 283.9K | 276.2K | -3% |
| math.zig | 312.6K | 305.3K | -2% |
+--------------+----------+----------+--------+
Previously the tag type was generated even if it was nonexistant,
triggering an assertion that an integer type should never have
zero bits. Now its only generated when the tag type is actually emitted.
When initializing a packed struct, we must ensure the result local
is zero'd. Previously we would do this by ensuring a new local is
allocated. Although a local is always zero by default, it meant that
if such an initialization was being done inside a loop, it would re-
use that very same local that could potentially still hold a different
value. Because this value is `or`'d with the value, it would result
in a miscompilation. By manually setting this result to 0, we guarantee
the correct behavior.
Previously we incorrectly assumed all memset's to have its element
abi-size be 1 byte. This would set the region of memory incorrectly.
We now have a more efficient loop, as well as support any element
type by re-using the `store` function for each element and moving
the pointer by 1 element.
Previously we would use the address of the slice itself, which would
result in miscompilations and accidently setting the memory region
of the slice itself, rather than based on the `ptr` field.
Previously when lowering a value of `elem_ptr` we would multiply the
abisize of the parent type by the index, rather than the element type.
This would result in an invalid pointer way beyond the correct pointer.
We now also pass the current offset to each recursive call to ensure
we do not miss inner offsets.
When we have a `ret_load` instruction with a zero-sized type which was
not an error, we would not emit any instruction. This resulted in
no `return` instruction and also not correctly resetting the global
stack_pointer.
This commit also enables the regular test runner for the WebAssembly
backend.
A copy was being made of a WValue variable, which meant the call
to `free` would insert the local that was being held by said WValue
was appended to the free list twice. This led to the same local being
reused even though it wasn't free and would lead to it being over-
written by a new value.
Rather than adding all values that were generated in the child branch,
we simply discard them as outer branches cannot refer to values
produced from an inner branch.
This new tag is used for freed locals that are not allowed to have any
remaining references pointing to it. This new tag allows us to easily
identify liveness bugs. Previously we would set the entire region to
`undefined` which would incorrectly set the tag to `function_index`,
making codegen think it was a valid `WValue` while it wasn't.
Make sure to increase the reference count for `intcast` when the
operand doesn't require any casting of the respective WebAssembly type.
Function arguments have a reserved slot, and therefore cannot be
re-used arbitrarily
This fix ensures that when we are shifting left or right,
both operands have the same WebAssembly type. e.g. it's not possible
to shift a 64 bit integer and 32 bit integer together and will fail
WebAssembly's validator. By first coercing the values to the same
type, we ensure we satisfy the validator.
This was a special type tag used for hacky stuff in Semantic Analysis.
Move the hacky stuff to use a dedicated `Air.Inst.Ref` instead.
This way, `var_args_param` is not involved in the type system or intern
pool.
Since #14819 this test failed with:
$ ../../../build/stage3/bin/zig test multi_writer.zig
multi_writer.zig:26:57: error: unable to evaluate comptime expression
var batch = std.event.Batch(Error!void, self.streams.len, .auto_async).init();
~~~~^~~~~~~~
referenced by:
Writer: multi_writer.zig:19:52
writer: multi_writer.zig:21:36
remaining reference traces hidden; use '-freference-trace' to see all reference traces
Thanks @jacobly for hints how to fix this on IRC.
* Avoid redundant words ("found")
- All compile errors are found by the compiler
* Avoid unnecessary prepositions ("with")
- There is a grammatically correct alternate word order without the
preposition.
This reverts commit 5aa9628de3c6637f45b9d8cf8cbd19c422a74f6f.
This is a breaking language change and I do not agree with it. Please go
through the proposal process on this one.
`@trap` is a special function that we know never returns so it should
behave just like `@panic` and `@compileError` do currently and cause the
"unreachable code" + "control flow is diverted here" compile error.
Currently, `@trap(); @trap();` does not cause this error. Now it does.
* When there is buffered cleartext, return it without calling the
underlying read function. This prevents buffer overflow due to space
used up by cleartext.
* Avoid clearing the buffer when the buffered cleartext could not be
completely given to the result read buffer, and there is some
buffered ciphertext left.
* Instead of rounding up the amount of bytes to ask for to the nearest
TLS record size, round down, with a minimum of 1. This prevents the
code path from being taken which requires extra memory copies.
* Avoid calling `@memcpy` with overlapping arguments.
closes#15590
When producing zig2.c, don't waste time emitting C code for subcommands
that won't be used, such as objcopy.
This takes zig2.c down from 111M to 109M, and sidesteps some unfortunate
warnings that are currently emitted by GCC.