Previously, the comments would be lost with the colons.
This required a substantial rewrite of renderAsm to determine how many
colons should be rendered.
- PEG / Parser Changes
All the changes made here are to places where the PEG was more
permissive than the parser. Changes to the parser make it more
permissive and changes to the PEG make it more strict. When choosing
between these two options for discrepancies, I opted for the choice
that was more natural and increased code readability.
Changes to the Parser
* Tuple types can now be `inline` and `extern` (e.g. `extern struct`).
* Break labels are now only consumed if both the colon and identifier
are present instead of failing if there is only a colon.
* Labeled blocks are no longer parsed in PrimaryExpr (so they are now
allowed to have CurlySuffixExpr) as in the PEG.
* While expressions can now be grouped on the same line.
* Added distinction in error messages for "a multiline string literal"
so places where only single string literals are allowed do not give
"expected 'a string literal', found 'a string literal'".
Changes to the PEG
* Made it so extern functions cannot have a body
* Made it so ... can be only the last function argument
* Made it so many item pointers can't have bit alignment
* Made it so asm inputs / outputs can not be multiline string literals
* Added distinction between block-level statements and regular
statements
-- Pointer Qualifier Order
The PEG allowed for duplicated qualifiers, which the parser did not.
The simplest fix for this was to make each be allowed zero or one times
which required giving them a order similar to how FnProto already
works. The chosen order is the same as used by zig fmt. The parser
still accepts them in any order similar to functions.
-- Backtracking
Made it so several places could not backtrack in the PEG. A common
pattern for this was (A / !A).
--- !ExprSuffix
Expressions ending with expressions now have !ExprSuffix after.
This change prevents expressions such as `if (a) T else U{}` being be
parsable as `(if (a) T else U){}`. It also stops some backtracking,
take for example:
`if (a) for (b) |c| d else |e| f`
It may seem at first that the else clause belongs to the `for`, however
it actually belongs to the `if` because for else-clauses cannot have a
payload. This is fixed by a new `KEYWORD_else / !KEYWORD_else`, however
this alone does not fix more complex cases such as:
`if (a) for (b) |c| d() else |e| f`
The PEG would first attempt to parse it as expected but fail due to the
new guard. It will then backtrack to
`if (a) (for (b) |c| d)() else |e| f`
which is surprising but avoids the new gaurd. So, !ExprSuffix is
required to disallow this type of backtracking.
--- !LabelableExpr
For identifiers, excluding labels is necessary despite ordered choice
due to pointer bit alignment. For example `*align(a : b: for (c) e) T`
could backtrack to `*align(a : b : (for (c) e)) T`.
--- !SinglePtrTypeStart
Prevents expressions like `break * break` which is parsed as
`break (*break)` backtracking to `(break) * (break)`
--- !BlockExpr
Prevents expressions like `test { {} = a; }` being backtracked to and
parsed as `test { ({} = a); }` (the parenthesis are just for
demonstration, that expression is not legal either)
--- !ExprStatement
In addition to splitting up block level statements, statements that are
also parsable as expressions are now part of ExprStatement to disallow
backtracking.
This generates zig ASTs from `testing.Smith` and is based off the
langref's PEG.
The choice to not build the Ast while generating and instead parsing it
afterwards makes the smith more versatile by not being tied to a single
implementation at a cost of efficiency.
Additionally, a new function `boolWeighted` was added to `Smith` due to
its frequent use in `AstSmith`.
Otherwise a different process may get a cache hit on the file while we still
have a writable fd open for it. This isn't actually a real problem in the sense
that running the file should just work as expected if the OS allows it. But
until very recently[0], the Linux kernel would give ETXTBSY in this case. So
make sure we close the file before letting other processes know that it's
usable.
closes https://codeberg.org/ziglang/zig/issues/31563
[0] https://github.com/torvalds/linux/commit/2a010c41285345da60cece35575b4e0af7e7bf44
This prevents a race between `alloc` and `free` where T1 receives memory
from `alloc` that is semantically about to be freed by T2 and still being
accessed, but the `free` is already visible to T1. Using acquire-release
here guarantees that any `free` is only published after all accesses to
the memory being freed have already happened.
Co-authored-by: Jacob Young <amazingjacob@gmail.com>
This prevents a race between `alloc` and `free` where T1 receives memory
from `alloc` that is semantically about to be freed by T2 and still being
accessed, but the `free` is already visible to T1. Using acquire-release
here guarantees that any `free` is only published after all accesses to
the memory being freed have already happened.
Co-authored-by: Jacob Young <amazingjacob@gmail.com>
This reverts commit 589bcb2544.
The scenario presented in the reverted commit cannot actually happen.
Even if there are two contiguous arena nodes N1 and N2 and the `end_index`
of N1 points to somewhere in N2, a `resize` can never lead to an increase
of the `end_index` of N1 since it checks whether it's `<= size` first.
A `resize`/`free` *can* decrease `end_index`, but even if it is wrongly
assumed that some allocation that belongs to N2 actually belongs to N1
based on the `end_index` of N1, it can only ever be decreased to the start
of the buffer of N2. That's because a valid allocation of N2 logically
cannot be at any lower address than N2 itself. And any point still in N2
can never also be in N1, so there's no danger of overwriting any other
allocations of N1.
Address two separate but related issues:
- Return value of `RtlQueryPerformanceFrequency` was used inconsistently; it
returns a nonzero value to indicate success.
- `timeoutToWindowsInterval` wasn't converting absolute deadlines back to the
Windows epoch before passing them to the system, which meant that values (in
the Unix epoch) were always in the distant past, so sleeps would return
immediately.
Fixes#31653
Some initial work towards https://codeberg.org/ziglang/zig/issues/31414.
Conclusion from this: Only x86-freebsd, x86-haiku, and x86-illumos remain time32
and are currently unfixable. I don't think the upstreams for any of these
targets actually care about them anymore (probably why they weren't migrated to
time64), so this is not a particularly big concern.
I split UTIME constants out from timespec because they were causing unreasonable
code duplication by being there.
I understand the temptation to exploit page size knowledge to make this function
faster, but I don't think this code can ever be compatible with any reasonable
set of pointer provenance/aliasing rules. At the very least, I don't believe it
is compatible with LLVM's.
closes https://github.com/ziglang/zig/issues/23184
It is now ignored for inputs from the corpus to ensure the filesystem
and process corpus stay in sync. For other (nondeterministic) inputs the
input builder is now reset.
The first issue is that when len(Sn) >= 128,
we perform Sn xor D instead of the Sn xorend D
that is specified in RFC 5297.
The second issue is that we truncate the Sn
if it is larger than 4096 bytes, which could
lead to collisions between inputs. We solve
this by absoring the Sn into the CMAC state
perform the last 16 bytes, xoring those 16
bytes with D as described in the first issue,
and then updating and squeezing the CMAC.
As established in 048e38624e and d70bd0b37e, mutexes should use a strong
cmpxchg when attempting to lock to guarantee that they actually succeed
if they aren't locked yet.
Also deletes an unused near-duplicate of `mutexLock()`.
The `cmpxchgWeak` in `setIpcFile` could lead to the IPC file not being set
even though there's still a slot available because one or more slots were
spuriously skipped.
The `cmpxcheWeak` in `serialize` could lead to an unused IPC slot not
being locked and used even though it could be.
Having `std.Io.Uring` contain OpenError error set
allows handling of OperationUnsupported specifically for `.openat`,
while avoiding propagating this error to the more general
`File.OpenError`.
This more specific subset also eliminated 2 unreachable prongs that
previously inherited from `File.OpenError`.
Added comments when handling OperationUnsupported, making it clear it is
an unexpected error when TMPFILE bit is not set.
- plain old data ftw
- 177K -> 151K
- data bypasses Sema
This change is not really important but it was nice to explore best
practices for data like this.
When I measured building the compiler, I found no statistically
significant difference in compilation time.