Both of these instructions were previously under a special case in
`rvalue` which resulted in every reference to such an instruction adding
a new `ref` instruction. This had the effect that, for instance,
`&a != &a` for parameters. Deduplicating these `ref` instructions was
problematic for different reasons.
For `alloc_inferred`, the problem was that it's not valid to `ref` the
alloc until the allocation has been resolved (`resolve_inferred_alloc`),
but `AstGen.appendBodyWithFixups` would place the `ref` directly after
the `alloc_inferred`. This is solved by bringing
`resolve_inferred_alloc` in line with `make_ptr_const` by having it
*return* the final pointer, rather than modifying `sema.inst_map` of the
original `alloc_inferred`. That way, the `ref` refers to the
`resolve_inferred_alloc` instruction, so is placed immediately after it,
avoiding this issue.
For `param`, the problem is a bit trickier: `param` instructions live in
a body which must contain only `param` instructions, then a
`func{,_inferred,_fancy}`, then a `break_inline`. Moreover, `param`
instructions may be referenced not only by the function body, but also
by other parameters, the return type expression, etc. Each of these
bodies requires separate `ref` instructions. This is solved by pulling
entries out of `ref_table` after evaluating each component of the
function declaration, and appending the refs later on when actually
putting the bodies together. This gives way to another issue: if you
write `fn f(x: T) @TypeOf(x.foo())`, then since `x.foo()` takes a
reference to `x`, this `ref` instruction is now in a comptime context
(outside of the `@TypeOf` ZIR body), so emits a compile error. This is
solved by loosening the rules around `ref` instructions; because they
are not side-effecting, it is okay to allow `ref` of runtime values at
comptime, resulting in a runtime-known value in a comptime scope. We
already apply this mechanism in some cases; for instance, it's why
`runtime_array.len` works in a `comptime` context. In future, we will
want to give similar treatment to many operations in Sema: in general,
it's fine to apply runtime operations at comptime provided they don't
have side effects!
Resolves: #22140
Frame pointers make both debugging and profiling work better, and the overhead
is reportedly 1% or less for typical programs [0]. I think the pros outweigh the
cons here. People who *really* care about that 1% can simply use the
-fomit-frame-pointer option to reclaim it. For ReleaseSmall, though, it makes
sense to omit frame pointers by default for the sake of code size, as we already
strip the binary in this case anyway.
Closes#22161.
[0] https://www.brendangregg.com/blog/2024-03-17/the-return-of-the-frame-pointers.html
* This warning's wording is actually inaccurate when using the -fno-compiler-rt
or -rtlib=none options.
* It's not all that helpful; it's already understood that these libraries are
part of the compiler, so printing a warning is just noise. In practice, this
warning would always happen when building upstream musl, for example.
* We don't warn when we satisfy -lunwind using our bundled libunwind either, or
various libc libraries using our bundled libc, or when providing libc++, etc.
So I really don't think we should be warning here either.
This is GCC's equivalent to compiler-rt. The two libraries have a huge overlap
in exported symbols, so we may as well satisfy it this way to increase
compatibility with build systems in the wild.
The real libgcc_s is a compiler-provided library; it works just fine with both
glibc and musl. There's no reason that I can see for this check to be limited to
glibc-based targets.
This is a library that ships with GCC and provides fallback implementations of
atomic intrinsics where necessary. Since we do the same in our compiler-rt
implementation, and since some build systems insist on passing -latomic even
for Clang (which zig cc masquerades as), just satisfy this dependency by way of
compiler-rt.
Closes#22165.
It doesn't appear that targeting bridgeOS is meaningfully supported by Apple.
Even LLVM/Clang appear to have incomplete support for it, suggesting that Apple
never bothered to upstream that support. So there's really no sense in us
pretending to support this.
This fix doesn't matter at all in the grand scheme of things, but I
think the story behind it is perhaps curious, as it might point at a
design flaw in the Sema's error reporting API. So, a story:
On lobsters, there's a rather heated discussion on the merits on RAII vs
defer. I don't really like participating in heating discussions, but
also sort of can't stop thinking about this.
My own personal experience with Zig's defer and errdefer is that they
are fiddly to get right consistency --- if a program has a lot of
resource management to do, I _always_ mess up at least one
defer/errdefer. I've found my internal peace by just avoiding
spread-out, "pox" resource management, and instead centralizing resource
ownership under one of the following patterns:
* Either the thing is acquired and released in main
* Or main allocates N instances of thing, and then the rest of the code
explicitly juggles this finite pool of N. Notably, this juggling
typically doesn't involve defer/errdefer at all, as, at this level of
precision, there are no `try`s left, so you only code the happy path
* Or there's some sort of arena thing, where a bunch of resources have a
single owner, the user's don' bother cleaning up their resources, and
instead the owner does it once at the end.
So I wanted to make a lobster.rs comment in the vein of "yeah, if your
program is mostly about resource management, then Zig could be kinda a
pain, but that's friction tells you something: perhaps your program
shouldn't be about resource management, and instead it should be doing
what it is supposed to do?". And, as an evidence for my claim, I wanted
to point out some large body of Zig code which doesn't have a lot of
errdefers.
So, I cracked opened Sema.zig, `ctrl+f` for `defer`, saw whopping 400
something occupancies, and my heart skipped a bit. Looking at the
occurrences, _some_ of them were non-resource-related usages of defer.
But a lot of them were the following pattern:
```zig
const msg = try sema.errMsg(src, "comptime control flow inside runtime block", .{});
errdefer msg.destroy(sema.gpa);
```
This is exactly the thing that I know _I_ can't get right consistently!
So, at this point, I made a prediction that at least one of `errdefer`s
is missing. So, I looked at the first few `const msg = try` and of
course found one without `errdefer`.
I am at 0.8 that, even with this PR applied, the claim will still stand
--- there will be `errdefer` missing. So it feels like some API
re-design is in order, to make sure individual error messages are not
resources.
Could Sema just own all partially-constructed error messages, and, at a
few known safe-points:
* if the control flow is normal, assert that there are no in-progress
error messages
* if we are throwing an error, go and release messages immediately?
I am unlikely to do the actual refactor here, but I think it's worth
highlighting the overall pattern here.
PS: I am only 0.9 sure that what I've found is indeed a bug! I don't
understand the code, I did a dumb text search, so I _could_ have made a
fool of myself here :P
If present, these headers are usable even when compiling for older C language
versions.
Most notably, this enables zig.h atomics to work with slimcc and TinyCC in C99
mode (and earlier).