This comment is now deleted because the task is completed in this
commit:
```
// TODO: Update this to behave like `beginComptimePtrLoad` and properly check/use
// `container_ty` and `array_ty`, instead of trusting that the parent decl type
// matches the type used to derive the elem_ptr/field_ptr/etc.
//
// This is needed because the types will not match if the pointer we're mutating
// through is reinterpreting comptime memory.
```
The main strategy is to change the ComptimePtrMutationKit struct so that
instead of `val: *Value` it now returns a tagged union which can be one
of three possibilities:
* The pointer type matches the actual comptime Value so a direct
modification is possible. Before this commit, the implementation
incorrectly assumed this was always the case.
* In the case of needing to write through a reinterpreted pointer, a
mutable base Value pointer is provided along with a byte offset
pointing to the element value in virtual memory.
* Otherwise, it means a compile error must be emitted because one or
both of the types (the owner of the value, or the pointer type being
used to write through) do not have a well-defined memory layout.
After calling beginComptimePtrMutation, the one callsite now switches on
this tagged union and does the appropriate thing. The main new logic is
for the second case, which involves pointer reinterpretation, which now
takes this strategy:
1. write the base value to a memory buffer.
2. perform the pointer store at the proper byte offset, thereby
modifying a subset of the buffer.
3. read the base value from the memory buffer, overwriting the old base
value.
This commit does not change any behavior, but changes the type of
the runtime_index field from u32 to a non-exhaustive enum. This allows
us to put `std.math.maxInt(u32)` only in the enum type definition and
give it an official meaning.
Rather than storing all the shifts in temporaries, we perform the correct
shifting without temporaries. This makes the runtime code more performant
and also the backend code is simplified as we have a singular abstraction.
This does however not support floats of bitsizes
different than 32 or 64. f16, f80, f126 will require
support for compiler-rt and are out-of-scope for this commit.
Signed integers are currently not supported either.
llvm: dump failed module when -femit-llvm-ir set
print_air:
* print fully qualified name
* use Type.fmt and Value.fmtValue, fmtDebug is useless
TypedValue
* handle anon structs and tuples
* fix bugs
This comptime gate is needed to make sure that purely single-threaded
programs don't generate calls to the std.Thread API.
WASI targets successfully build again with this change.
The function `writeDbgInfoNopsBuffered` was based on the function
`pwriteDbgInfoNops`, originally written by me, and then modified to
write to a memory buffer instead of an open file. When writing to a
file, any extra bytes beyond the end of the file extend the size of
the file, and the function body of `pwriteDbgInfoNops` takes advantage
of this when `next_padding_bytes` causes the write to go beyond the
end of the file. However, when writing to a memory buffer, the
underlying array list must be expanded if the write would cause the
buffer to expand.
Note that the current documentation for the `-z noexecstack` is
incorrect. This indicates that an object *does not* require an
executable stack.
This is actually the default of LLD, and there has never been a way to
override this default by passing `-z execstack` to LLD.
This commit removes the redundant `-z noexecstack` option from
zig build-exe/build-lib/build-obj and ignores the option if passed
to zig cc for compatibility.
As far as I can tell, there is no reason for code to require an
executable stack. This option only exists because the stack was
originally executable by default and some programs came to depend
on that behavior. Instead, mprotect(2) may be used to make memory
pages executable.
I'm not really happy with parsing compile errors; I think we should just
be checking that the expected compile error matches the actual rendered
version. I will save that change for a later date however.
And use it to debug a LazySrcLoc in stage2 that is set to a bogus value.
The actual fix in this commit is:
```diff
- try sema.emitBackwardBranch(&child_block, call_src);
+ try sema.emitBackwardBranch(block, call_src);
```
Whenever a `ref` instruction is needed, it is created and saved in
`AstGen.ref_table` instead of being immediately appended to the current
block body. Then, when the referenced instruction is being added to the
parent block (e.g. from setBlockBody), if it has a ref_table entry, then
the ref instruction is added directly after the instruction being referenced.
This makes sure two properties are upheld:
1. All pointers to the same locals return the same address. This is required
to be compliant with the language specification.
2. `ref` instructions will dominate their uses. This is a required property
of ZIR.
A complication arises when a ref instruction refs another ref
instruction. The logic in appendBodyWithFixups must take this into
account, recursively handling ref refs.
Full RELRO is a hardening feature that makes it impossible to perform
certian attacks involving overwriting parts of the Global Offset Table
to invoke arbitrary code.
It requires all symbols to be resolved before execution of the program
starts which may have an impact on startup time. However most if
not all popular Linux distributions enable full RELRO by default for
all binaries and this does not seem to make a noticeable difference
in practice.
"Partial RELRO" is equivalent to `-z relro -z lazy`.
"Full RELRO" is equivalent to `-z relro -z now`.
LLD defaults to `-z relro -z lazy`, which means Zig's current `-z relro`
option has no effect on LLD's behavior.
The changes made by this commit are as follows:
- Document that `-z relro` is the default and add `-z norelro`.
- Pass `-z now` to LLD by default to enable full RELRO by default.
- Add `-z lazy` to disable passing `-z now`.